动态

详情 返回 返回

Scala語法篇 - 动态 详情

Scala基礎篇

數據類型

下表中列出的數據類型都是對象,可以直接對它們調用方法。

數據類型 描述
Byte 8位有符號補碼整數。數值區間為 -128 到 127
Short 16位有符號補碼整數。數值區間為 -32768 到 32767
Int 32位有符號補碼整數。數值區間為 -2147483648 到 2147483647
Long 64位有符號補碼整數。數值區間為 -9223372036854775808 到 9223372036854775807
Float 32 位, IEEE 754 標準的單精度浮點數
Double 64 位 IEEE 754 標準的雙精度浮點數
Char 16位無符號Unicode字符, 區間值為 U+0000 到 U+FFFF
String 字符序列
Boolean true或false
Unit 表示無值,和其他語言中void等同。用作不返回任何結果的方法的結果類型。Unit只有一個實例值,寫成()。
Null null 或空引用
Nothing Nothing類型在Scala的類層級的最底端;它是任何其他類型的子類型。
Any Any是所有其他類的超類
AnyRef AnyRef類是Scala裏所有引用類(reference class)的基類

表示Long類型,在數字後面添加L或者l作為後綴;浮點數後面有f或者F後綴時,表示Float類型,否則就是Double

變量

用關鍵詞“var”聲明變量,關鍵詞"val"聲明常量。

var myName : String = "gyt"
val myAge : Int = 21 

scala中不一定要指明數據類型,其數據類型通過變量或常量的初始值推斷出來的,因此,在沒有指明數據類型的情況下,必須要給出初始值。

訪問修飾符

private關鍵詞修飾,只能被當前類以及當前類的內部類訪問到,外層類訪問不到。

class Outer{
    class Inner{
        private def f(){
            println("f")
        }
        class InnerMost{
            f() // 正確
        }
    }
    (new Inner).f() //錯誤
}

protected關鍵詞修飾,只能被當前類的子類訪問。

package p {
    class Super {
        protected def f() {println("f")}
    }
    class Sub extends Super {
        f()
    }
    class Other {
        (new Super).f() //錯誤
    }
}

沒有指定任何修飾符,默認為public,在任何地方都可以被訪問。

條件和循環

以下是IF...ELSE語句實例。

object Test {
   def main(args: Array[String]) {
      var x = 30;

      if( x == 10 ){
         println("X 的值為 10");
      }else if( x == 20 ){
         println("X 的值為 20");
      }else if( x == 30 ){
         println("X 的值為 30");
      }else{
         println("無法判斷 X 的值");
      }
   }
}

以下是一個使用了 i to j 語法(包含 j)的實例,箭頭 <- 用於為變量 a 賦值。

object Test {
   def main(args: Array[String]) {
      var a = 0;
      // for 循環
      for( a <- 1 to 10){
         println( "Value of a: " + a );
      }
   }
}

for 循環 中你可以使用分號;來設置多個區間,它將迭代給定區間所有的可能值。

object Test {
   def main(args: Array[String]) {
      var a = 0;
      var b = 0;
      // for 循環
      for( a <- 1 to 3; b <- 1 to 3){
         println( "Value of a: " + a );
         println( "Value of b: " + b );
      }
   }
}

for 循環集合的語法如下。

object Test {
   def main(args: Array[String]) {
      var a = 0;
      val numList = List(1,2,3,4,5,6);

      // for 循環
      for( a <- numList ){
         println( "Value of a: " + a );
      }
   }
}

你可以將 for 循環的返回值作為一個變量存儲。

object Test {
   def main(args: Array[String]) {
      var a = 0;
      val numList = List(1,2,3,4,5,6,7,8,9,10);

      // for 循環
      var retVal = for{ a <- numList 
                        if a != 3; if a < 8
                      }yield a

      // 輸出返回值
      for( a <- retVal){
         println( "Value of a: " + a );
      }
   }
}

函數式編程(重點)

函數式編程:對於相同的輸入永遠會得到相同的輸出,而且沒有任何可以觀察的副作用,也不依賴外部的環境狀態。參考什麼是函數式編程?。

Scala中函數是為完成某一功能的程序語句的集合,類中定義的函數稱之為方法。下面是方法的一個實例。

object add{
   def addInt( a:Int, b:Int ) : Int = {
      var sum:Int = 0
      sum = a + b

      return sum
   }
}

可變參數:我們不需要指定函數參數的個數,可以向函數傳入可變長度參數列表。通過在參數的類型之後放一個星號來設置可變參數(可重複的參數)。

object Test {
   def main(args: Array[String]) {
        printStrings("Runoob", "Scala", "Python");
   }
   def printStrings( args:String* ) = {
      var i : Int = 0;
      for( arg <- args ){
         println("Arg value[" + i + "] = " + arg );
         i = i + 1;
      }
   }
}

默認參數: scala可以為函數參數指定默認參數值,使用了默認參數,你在調用函數的過程中可以不需要傳遞參數,這時函數就會調用它的默認參數值,如果傳遞了參數,則傳遞值會取代默認值。

object Test {
   def main(args: Array[String]) {
        println( "返回值 : " + addInt() );
   }
   def addInt( a:Int=5, b:Int=7 ) : Int = {
      var sum:Int = 0
      sum = a + b

      return sum
   }
}

匿名函數:箭頭左邊是參數列表,右邊是函數體。

var inc = (x: Int) => {x+1}
var x = inc(7) - 1

//定義一個函數,以函數作為參數輸入
def f(func: String => Unit): Unit = {
    func("gyt")
}
var fun = (name: String) => {println(name)}
f(fun)

傳名調用:傳遞的不是具體的值,而是代碼塊。和一般的傳值調用相比,每次使用傳名調用時,解釋器都會計算一次表達式的值。

def f1(): Int = {
    println("f1被調用")
    12
}
def f2(a: => Int): Unit = {
    println(a)
    println(a)
}
f2(f1())

至簡原則

(1)函數中的return可以省略,以最後一行代碼作為代碼塊的返回值。

def f1(name: String): String = {
    name
}

(2)如果函數體只有一行代碼,可以省略花括號。

def f2(name: String): String = name

(3)如果編譯器可以推斷出來返回值,那麼可以省略(:和返回值類型一起省略)。有意思的是,到這一步,scala函數的形式形如數學中的f(x) = y。

def f3(name: String) = name

(4)如果有return,則(3)不適用。

(5)如果返回值是Unit,可以省略等號和返回值,但是此時花括號不能省略。

def f4(name: String) {
    println(name)
}

(6)如果函數沒有參數,那麼調用它的時候可以直接用函數名。不用加“()”。

閉包:如果一個函數,訪問到它的外部(局部)變量的值,那麼這個函數和它所處的環境,稱為閉包。

柯里化:將原來接受兩個參數的函數變成新的接受一個參數的函數的過程。新的函數返回一個以原有第二個參數為參數的函數。

object Test {
   def main(args: Array[String]) {
      val str1:String = "Hello, "
      val str2:String = "Scala!"
      println( "str1 + str2 = " +  strcat(str1)(str2) )
   }

   def strcat(s1: String)(s2: String) = {
      s1 + s2
   }
}

字符串

在 Scala 中,字符串的類型實際上是 Java String,它本身沒有 String 類。

序號 方法及描述
1 char charAt(int index)返回指定位置的字符
2 int compareTo(Object o)比較字符串與對象
3 int compareTo(String anotherString)按字典順序比較兩個字符串
4 int compareToIgnoreCase(String str)按字典順序比較兩個字符串,不考慮大小寫
5 String concat(String str)將指定字符串連接到此字符串的結尾
6 boolean contentEquals(StringBuffer sb)將此字符串與指定的 StringBuffer 比較。
7 static String copyValueOf(char[] data)返回指定數組中表示該字符序列的 String
8 static String copyValueOf(char[] data, int offset, int count)返回指定數組中表示該字符序列的 String
9 boolean endsWith(String suffix)測試此字符串是否以指定的後綴結束
10 boolean equals(Object anObject)將此字符串與指定的對象比較
11 boolean equalsIgnoreCase(String anotherString)將此 String 與另一個 String 比較,不考慮大小寫
12 byte getBytes()使用平台的默認字符集將此 String 編碼為 byte 序列,並將結果存儲到一個新的 byte 數組中
13 byte[] getBytes(String charsetName使用指定的字符集將此 String 編碼為 byte 序列,並將結果存儲到一個新的 byte 數組中
14 void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)將字符從此字符串複製到目標字符數組
15 int hashCode()返回此字符串的哈希碼
16 int indexOf(int ch)返回指定字符在此字符串中第一次出現處的索引
17 int indexOf(int ch, int fromIndex)返回在此字符串中第一次出現指定字符處的索引,從指定的索引開始搜索
18 int indexOf(String str)返回指定子字符串在此字符串中第一次出現處的索引
19 int indexOf(String str, int fromIndex)返回指定子字符串在此字符串中第一次出現處的索引,從指定的索引開始
20 String intern()返回字符串對象的規範化表示形式
21 int lastIndexOf(int ch)返回指定字符在此字符串中最後一次出現處的索引
22 int lastIndexOf(int ch, int fromIndex)返回指定字符在此字符串中最後一次出現處的索引,從指定的索引處開始進行反向搜索
23 int lastIndexOf(String str)返回指定子字符串在此字符串中最右邊出現處的索引
24 int lastIndexOf(String str, int fromIndex)返回指定子字符串在此字符串中最後一次出現處的索引,從指定的索引開始反向搜索
25 int length()返回此字符串的長度
26 boolean matches(String regex)告知此字符串是否匹配給定的正則表達式
27 boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)測試兩個字符串區域是否相等
28 boolean regionMatches(int toffset, String other, int ooffset, int len)測試兩個字符串區域是否相等
29 String replace(char oldChar, char newChar)返回一個新的字符串,它是通過用 newChar 替換此字符串中出現的所有 oldChar 得到的
30 String replaceAll(String regex, String replacement使用給定的 replacement 替換此字符串所有匹配給定的正則表達式的子字符串
31 String replaceFirst(String regex, String replacement)使用給定的 replacement 替換此字符串匹配給定的正則表達式的第一個子字符串
32 String[] split(String regex)根據給定正則表達式的匹配拆分此字符串
33 String[] split(String regex, int limit)根據匹配給定的正則表達式來拆分此字符串
34 boolean startsWith(String prefix)測試此字符串是否以指定的前綴開始
35 boolean startsWith(String prefix, int toffset)測試此字符串從指定索引開始的子字符串是否以指定前綴開始。
36 CharSequence subSequence(int beginIndex, int endIndex)返回一個新的字符序列,它是此序列的一個子序列
37 String substring(int beginIndex)返回一個新的字符串,它是此字符串的一個子字符串
38 String substring(int beginIndex, int endIndex)返回一個新字符串,它是此字符串的一個子字符串
39 char[] toCharArray()將此字符串轉換為一個新的字符數組
40 String toLowerCase()使用默認語言環境的規則將此 String 中的所有字符都轉換為小寫
41 String toLowerCase(Locale locale)使用給定 Locale 的規則將此 String 中的所有字符都轉換為小寫
42 String toString()返回此對象本身(它已經是一個字符串!)
43 String toUpperCase()使用默認語言環境的規則將此 String 中的所有字符都轉換為大寫
44 String toUpperCase(Locale locale)使用給定 Locale 的規則將此 String 中的所有字符都轉換為大寫
45 String trim()刪除指定字符串的首尾空白符
46 static String valueOf(primitive data type x)返回指定類型參數的字符串表示形式

數組

Scala 語言中提供的數組是用來存儲固定大小的同類型元素。下面是聲明數組的三種方式。

var z:Array[String] = new Array[String](3)
var zz = new Array[String](3)
var zzz = Array("Runoob", "Baidu", "Google")

模式匹配

一個模式匹配包含了一系列備選項,每個都開始於關鍵字 case。每個備選項都包含了一個模式及一到多個表達式。箭頭符號 => 隔開了模式和表達式。

object Test {
   def main(args: Array[String]) {
      println(matchTest("two"))
      println(matchTest("test"))
      println(matchTest(1))
      println(matchTest(6))

   }
   def matchTest(x: Any): Any = x match {
      case 1 => "one"
      case "two" => 2
      case y: Int => "scala.Int"
      case _ => "many"
   }
}

實例中第一個 case 對應整型數值 1,第二個 case 對應字符串值 two,第三個 case 對應類型模式,用於判斷傳入的值是否為整型,相比使用isInstanceOf來判斷類型,使用模式匹配更好。第四個 case 表示默認的全匹配備選項,即沒有找到其他匹配時的匹配項,類似 switch 中的 default。

object Test {
   def main(args: Array[String]) {
        val alice = new Person("Alice", 25)
        val bob = new Person("Bob", 32)
        val charlie = new Person("Charlie", 32)
   
    for (person <- List(alice, bob, charlie)) {
        person match {
            case Person("Alice", 25) => println("Hi Alice!")
            case Person("Bob", 32) => println("Hi Bob!")
            case Person(name, age) =>
               println("Age: " + age + " year, name: " + name + "?")
         }
      }
   }
   // 樣例類
   case class Person(name: String, age: Int)
}

使用了case關鍵字的類定義就是樣例類(case classes),樣例類是種特殊的類,經過優化以用於模式匹配。

迭代器

Scala Iterator(迭代器)不是一個集合,它是一種用於訪問集合的方法。迭代器 it 的兩個基本操作是 nexthasNext。調用 it.next() 會返回迭代器的下一個元素,並且更新迭代器的狀態。調用 it.hasNext() 用於檢測集合中是否還有元素。讓迭代器 it 逐個返回所有元素最簡單的方法是使用 while 循環:

object Test {
   def main(args: Array[String]) {
      val it = Iterator("Baidu", "Google", "Runoob", "Taobao")
      
      while (it.hasNext){
         println(it.next())
      }
   }
}

下表列出了Scala Iterator常用的方法:

序號 方法及描述
1 def hasNext: Boolean如果還有可返回的元素,返回true。
2 def next(): A返回迭代器的下一個元素,並且更新迭代器的狀態
3 def ++(that: => Iterator[A]): Iterator[A]合併兩個迭代器
4 def ++[B >: A](that :=> GenTraversableOnce[B]): Iterator[B]合併兩個迭代器
5 def addString(b: StringBuilder): StringBuilder添加一個字符串到 StringBuilder b
6 def addString(b: StringBuilder, sep: String): StringBuilder添加一個字符串到 StringBuilder b,並指定分隔符
7 def buffered: BufferedIterator[A]迭代器都轉換成 BufferedIterator
8 def contains(elem: Any): Boolean檢測迭代器中是否包含指定元素
9 def copyToArray(xs: Array[A], start: Int, len: Int): Unit將迭代器中選定的值傳給數組
10 def count(p: (A) => Boolean): Int返回迭代器元素中滿足條件p的元素總數。
11 def drop(n: Int): Iterator[A]返回丟棄前n個元素新集合
12 def dropWhile(p: (A) => Boolean): Iterator[A]從左向右丟棄元素,直到條件p不成立
13 def duplicate: (Iterator[A], Iterator[A])生成兩個能分別返回迭代器所有元素的迭代器。
14 def exists(p: (A) => Boolean): Boolean返回一個布爾值,指明迭代器元素中是否存在滿足p的元素。
15 def filter(p: (A) => Boolean): Iterator[A]返回一個新迭代器 ,指向迭代器元素中所有滿足條件p的元素。
16 def filterNot(p: (A) => Boolean): Iterator[A]返回一個迭代器,指向迭代器元素中不滿足條件p的元素。
17 def find(p: (A) => Boolean): Option[A]返回第一個滿足p的元素或None。注意:如果找到滿足條件的元素,迭代器會被置於該元素之後;如果沒有找到,會被置於終點。
18 def flatMap[B](f: (A) => GenTraversableOnce[B]): Iterator[B]針對迭代器的序列中的每個元素應用函數f,並返回指向結果序列的迭代器。
19 def forall(p: (A) => Boolean): Boolean返回一個布爾值,指明 it 所指元素是否都滿足p。
20 def foreach(f: (A) => Unit): Unit在迭代器返回的每個元素上執行指定的程序 f
21 def hasDefiniteSize: Boolean如果迭代器的元素個數有限則返回 true(默認等同於 isEmpty)
22 def indexOf(elem: B): Int返回迭代器的元素中index等於x的第一個元素。注意:迭代器會越過這個元素。
23 def indexWhere(p: (A) => Boolean): Int返回迭代器的元素中下標滿足條件p的元素。注意:迭代器會越過這個元素。
24 def isEmpty: Boolean檢查it是否為空, 為空返回 true,否則返回false(與hasNext相反)。
25 def isTraversableAgain: BooleanTests whether this Iterator can be repeatedly traversed.
26 def length: Int返回迭代器元素的數量。
27 def map[B](f: (A) => B): Iterator[B]將 it 中的每個元素傳入函數 f 後的結果生成新的迭代器。
28 def max: A返回迭代器迭代器元素中最大的元素。
29 def min: A返回迭代器迭代器元素中最小的元素。
30 def mkString: String將迭代器所有元素轉換成字符串。
31 def mkString(sep: String): String將迭代器所有元素轉換成字符串,並指定分隔符。
32 def nonEmpty: Boolean檢查容器中是否包含元素(相當於 hasNext)。
33 def padTo(len: Int, elem: A): Iterator[A]首先返回迭代器所有元素,追加拷貝 elem 直到長度達到 len。
34 def patch(from: Int, patchElems: Iterator[B], replaced: Int): Iterator[B]返回一個新迭代器,其中自第 from 個元素開始的 replaced 個元素被迭代器所指元素替換。
35 def product: A返回迭代器所指數值型元素的積。
36 def sameElements(that: Iterator[_]): Boolean判斷迭代器和指定的迭代器參數是否依次返回相同元素
37 def seq: Iterator[A]返回集合的系列視圖
38 def size: Int返回迭代器的元素數量
39 def slice(from: Int, until: Int): Iterator[A]返回一個新的迭代器,指向迭代器所指向的序列中從開始於第 from 個元素、結束於第 until 個元素的片段。
40 def sum: A返回迭代器所指數值型元素的和
41 def take(n: Int): Iterator[A]返回前 n 個元素的新迭代器。
42 def toArray: Array[A]將迭代器指向的所有元素歸入數組並返回。
43 def toBuffer: Buffer[B]將迭代器指向的所有元素拷貝至緩衝區 Buffer。
44 def toIterable: Iterable[A]Returns an Iterable containing all elements of this traversable or iterator. This will not terminate for infinite iterators.
45 def toIterator: Iterator[A]把迭代器的所有元素歸入一個Iterator容器並返回。
46 def toList: List[A]把迭代器的所有元素歸入列表並返回
47 def toMap[T, U]: Map[T, U]將迭代器的所有鍵值對歸入一個Map並返回。
48 def toSeq: Seq[A]將代器的所有元素歸入一個Seq容器並返回。
49 def toString(): String將迭代器轉換為字符串
50 def zip[B](that: Iterator[B]): Iterator[(A, B)返回一個新迭代器,指向分別由迭代器和指定的迭代器 that 元素一一對應而成的二元組序列

Add a new 评论

Some HTML is okay.