Scala基本類型
Scala中的基本數據類型如下圖:
(來源:Programming in scala)
從上表中可以看出,Scala的基本數據類型與Java中的基本數據類型是一一對應的,不同的是Scala的基本數據類型頭字母必須大寫,本節以Int、Long、String、Char、Double及Float類型為例介紹Scala的基本類型定義
整數類型變量定義:
//16進制定義法 scala> val x=0x29 x: Int = 41 1 //十進制定義法 scala> val x=41 x: Int = 41 //八進制定義法 scala> 051 res0: Int = 41
//Double類型定義,直接輸入浮點數,編譯器會將其自動推斷為Double類型 scala> val doubleNumber=3.141529 doubleNumber: Double = 3.141529 //要定義Float類型浮點數,需要在浮點數后面加F或f scala> val floatNumber=3.141529F floatNumber: Float = 3.141529 scala> val floatNumber=3.141529f floatNumber: Float = 3.141529
浮點類型的變量還可以采用指數表示法,如
//浮點數指數表示法,e也可以是大寫E,0.314529e1與0.314529*10等同 scala> val floatNumber=0.314529e1 floatNumber: Double = 3.14529
字符變量定義:
//字符定義,用''將字符包裹 scala> var charLiteral='A' charLiteral: Char = A
常用特殊字符包括
\n 換行符,其Unicode編碼為 (\u000A)
\b 回退符,其Unicode編碼為 (\u0008)
\t tab制表符 ,其Unicode編碼(\u0009)
\” 雙引號,其Unicode編碼為 (\u0022)
\’ 單引號,其Unicode編碼為 (\u0027)
\ 反斜桿,其Unicode編碼為(\u005C)
字符串變量定義:
//字符串變量用""包裹 scala> val helloWorld="Hello World" helloWorld: String = Hello World //要定義"Hello World",可以加入轉義符\ scala> val helloWorldDoubleQuote="\"Hello World\"" helloWorldDoubleQuote: String = "Hello World" //如果希望能夠原樣輸出字符串中的內容,則用三個引號"""將字符串包裹起來,如 scala> println(""" hello cruel world, \n \\\\ \b \\, I am " experienced" programmer""") hello cruel world, \n \\\\ \b \\, I am " experienced" programmer
布爾類型定義:
scala> var x=true x: Boolean = true
Scala基本類型操作
在Scala中一切操作皆方法,這意味着Scala中的一切皆為對象。
任何方法都可以是操作符
Scala里的操作符不是特殊的語法:任何方法都可以是操作符。到底是方法還是操作符取決於你如何使用它。
例如:
如果寫成s.indexOf('0’),indexOf就不是操作符。
如果寫成s indexOf '0'那么indexOf就是操作符,因為你以操作符標注方式使用它。
Scala中的3類操作符:
- 中綴(infix)操作符(標注):操作符位於對象和傳遞給方法的參數或若干參數之間。例如:“7 + 2”。
- 前綴操(prefix)作符(標注):方法名被放在調用的對象之前。例如:- 7 里的“-”。只有+、-、!和~。
- 后綴(subfix)操作符(標注):方法放在對象之后。例如:“7 toLong”里的“toLong”。
與中綴操作符--兩個操作數,分別再操作符的左右兩側,前綴和后綴操作符都是一元(unary)的:它們僅有一個操作數。前綴方式中,操作數在操作符右邊。
算術操作:
//整數求和,編譯器會將其轉換為(1).+(2)執行 scala> var sumVlaue=1+2 sumVlaue: Int = 3 //前一語句等同於下列語句 scala> var sumVlaue=(1).+(2) sumVlaue: Int = 3 //操作符重載,編譯器會將其轉換為(1).+(2L)執行 scala> val longSum = 1 + 2L longSum: Long = 3 //減法 scala> 1-3 res5: Int = -2 //除法 scala> 1/3 res6: Int = 0 //取模 scala> 1%3 res7: Int = 1 //乘法 scala> 1L*3L res8: Long = 3 //scala中可以用+ -符號來表示正負數,例如-3 +3,並且可以加入到運算符當中 scala> var y=1+ -3 y: Int = -2
關系運算:
//>運算符 scala> 3 > -3 res12: Boolean = true //<運算符 scala> 3 < -3 res13: Boolean = false //<=運算符 scala> 3 <= -3 res14: Boolean = false //<=運算符 scala> 3 <=3 res15: Boolean = true //<=運算符 scala> !(3<= -3) res16: Boolean = true
邏輯運算:
//邏輯與:&& scala> val bool=true bool: Boolean = true scala> bool && bool res17: Boolean = true //邏輯或:|| scala> bool || bool res18: Boolean = true scala> bool || !bool res20: Boolean = true
位運算:
// 00000001 // 00000010 // 00000000 scala> 1 & 2 res24: Int = 0 // 00000001 // 00000010 // 00000011 scala> 1 | 2 res24: Int = 3 // 00000001 // 00000011 // 00000010 scala> 1 ^ 3 res24: Int =2 //00000001 //11111110 scala> ~1 res24: Int =-2 //左移位(shift left) //00000110 //00001100 scala> 6 << 1 res29: Int = 12 //右移位(shift left) //00000110 //00000011 scala> 6 >> 1 res28: Int = 3 //無符號右移(shift left) //11111111111111111111111111111111 //00000000000000000000000000000001 scala> -1 >>> 31 res32: Int = 1
對象比較:
scala> 1==1 res34: Boolean = true scala> 1==1.0 res35: Boolean = true scala> val x="Hello" x: String = Hello scala> val y="Hello" y: String = Hello //Scala中的對象比較不同於Java中的對象比較 //Scala基於內容比較,而java中比較的是引用,進行內容比較時須定義比較方法 scala> x==y res36: Boolean = true
運算符的優先級:
運算符優先級如下圖所示,* / %優先級最高,依次類推
圖片來源:Programming in Scala
Scala程序控制結構
if 的使用:
val x= if("hello"=="hell") 1 else 0
while 的使用:
def gcdLoop(x: Long, y: Long): Long = { var a = x var b = y while (a != 0) { val temp = a a = b % a b = temp } b }
do while的使用
var line = "" do { line = readLine() println("Read: "+ line) } while (line != "")
注意:與if不同的是,while與do while不能用作表達式,也即其返回值為Unit,在某些函數式編程語言中,刪除了while與do while程序控制結構,但scala仍然保留了while與do while,可見Scala並不是純函數式編程語言(另外一個重要原因是,scala函數定義時仍然可以用var指定參數)。
//利用if替代while控制結構 //這me做可以減少var變量的使用,程序結構也更簡單,表達能力更強 def gcd(x: Long, y: Long): Long = if (y == 0) x else gcd(y, x % y) var line = "" while ((line = readLine()) != "") // 錯誤,在Scala中不能這么用,因為Scala中的賦值操作返回的值是Unit,而""是String類型,不能進行比較,這是函數式編程語言特有的特點 println("Read: "+ line) //for循環的使用 scala> val filesHere = (new java.io.File(".")).listFiles //集合操作方式 scala> for (file <- filesHere) | println(file) //間接調用方式(不常用) for (i <- 0 to filesHere.length - 1) println(filesHere(i))
//程序中的<-被稱生成器(generator),在執行過程中,集合filesHere中(Array[File])的元素將依次賦給file,file類型為File,打印時調用其toString方法將文件名稱打印出來。
scala> val filesHere = (new java.io.File(".")).listFiles filesHere: Array[java.io.File] = Array(.\.android, .\.idea-build, .\.IdeaIC14, . \.ivy2, .\.m2, .\.sbt, .\.scala_history, .\AppData, .\Application Data, .\Contac ts, .\Cookies, .\Desktop, .\Documents, .\Downloads, .\Favorites, .\hello, .\Link s, .\Local Settings, .\Music, .\My Documents, .\NetHood, .\NTUSER.DAT, .\ntuser. dat.LOG1, .\ntuser.dat.LOG2, .\NTUSER.DAT{016888bd-6c6f-11de-8d1d-001e0bcde3ec}. TM.blf, .\NTUSER.DAT{016888bd-6c6f-11de-8d1d-001e0bcde3ec}.TMContainer0000000000 0000000001.regtrans-ms, .\NTUSER.DAT{016888bd-6c6f-11de-8d1d-001e0bcde3ec}.TMCon tainer00000000000000000002.regtrans-ms, .\ntuser.ini, .\Pictures, .\PrintHood, . \Recent, .\Roaming, .\Saved Games, .\Searches, .\SendTo, .\target, .\Templates, .\Videos, .\「開始」菜單) scala> for (file <- filesHere) | println(file) .\.android .\.idea-build .\.IdeaIC14 .\.ivy2 .\.m2 .\.sbt .\.scala_history .\AppData .\Application Data .\Contacts .\Cookies .\Desktop .\Documents .\Downloads .\Favorites .\hello .\Links .\Local Settings .\Music .\My Documents .\NetHood .\NTUSER.DAT .\ntuser.dat.LOG1 .\ntuser.dat.LOG2 .\NTUSER.DAT{016888bd-6c6f-11de-8d1d-001e0bcde3ec}.TM.blf .\NTUSER.DAT{016888bd-6c6f-11de-8d1d-001e0bcde3ec}.TMContainer000000000000000000 01.regtrans-ms .\NTUSER.DAT{016888bd-6c6f-11de-8d1d-001e0bcde3ec}.TMContainer000000000000000000 02.regtrans-ms .\ntuser.ini .\Pictures .\PrintHood .\Recent .\Roaming .\Saved Games .\Searches .\SendTo .\target .\Templates .\Videos .\「開始」菜單
<-生成器對其它類型的集合也適用,
scala> 1 to 5 res39: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5) scala> for(i <- res39) println("Iteration"+i) Iteration1 Iteration2 Iteration3 Iteration4 Iteration5 //也可直接簡寫成 scala> for(i <- 1 to 5) println("Iteration"+i) Iteration1 Iteration2 Iteration3 Iteration4 Iteration5 //如果不需要5出現,則用 scala> for(i <- 1 until 5) println("Iteration"+i) Iteration1 Iteration2 Iteration3 Iteration4
在for循環結構中還可以加入if進行過濾操作
val filesHere = (new java.io.File(".")).listFiles for (file <- filesHere if file.getName.endsWith(".scala")) println(file) //還可以加入多個過濾條件,用;隔開 for ( file <- filesHere if file.isFile; if file.getName.endsWith(".scala") ) println(file)
//多重循環的實現:
def fileLines(file: java.io.File) = scala.io.Source.fromFile(file).getLines.toList def grep(pattern: String) = for ( file <- filesHere if file.getName.endsWith(".scala"); line <- fileLines(file) if line.trim.matches(pattern) ) println(file +": "+ line.trim) grep(".*gcd.*") //前一個for相當於下列語句 def grep(pattern: String) = for ( file <- filesHere if file.getName.endsWith(".scala") ) for( line <- fileLines(file) if line.trim.matches(pattern) ) println(file +": "+ line.trim) grep(".*gcd.*")
生成返回結果
//每次循環將結果保留,當整個循環執行完畢,所有保留的值將會生成一個集合並返回 scala> def scalaFiles = | for { | file <- filesHere | if file.getName.endsWith(".scala") | } yield file scalaFiles: Array[java.io.File] //Array[File]到Array[Int]的轉換 scala> val forLineLengths = | for { | file <- filesHere | if file.getName.endsWith(".scala") | line <- fileLines(file) | trimmed = line.trim | if trimmed.matches(".*for.*") | } yield trimmed.length forLineLengths: Array[Int] = Array()
轉