目錄java
===sql
●Java中:編程
//數據類型 變量名 = 值; final int b = 2; b = 23; //錯誤!!! final修飾的變量不可變 int a = 1; a = 22;
●在Scala中:數組
//val/var 變量名:變量類型 = 變量值 val a:Int = 1 a =2 //錯誤!!!! val修飾的變量不能夠被從新賦值,相似於Java中的final var b:Int = 1 b = 2
●說明數據結構
var聲明的變量能夠從新賦值app
val聲明的變量不能夠從新賦值,或稱之爲不可變變量/只讀變量。至關於java裏用final修飾的變量dom
●注意:函數式編程
Scala中變量聲明類型能夠省略,解析器會根據值進行推斷函數
Scala中語句最後不須要添加分號oop
val和var聲明變量時都必須初始化
爲了減小可變性引發的bug,應該儘量地使用不可變變量val。(推薦使用val)
若是想在變量名、類名等定義中使用語法關鍵字(保留字),能夠配合反引號:
val `val` = 123 //(符號爲鍵盤上Esc下面的鍵)
●Type關鍵字
Scala 裏能夠經過type 關鍵字來聲明類型。
type 至關於聲明一個類型別名:
// 把String 類型用S 代替 type S = String val name: S = "bigdata" println (name)
●懶值
應用場景
當val被聲明爲lazy時,初始化將被推遲,只有當這個變量真正被使用到的時候,變量的賦值代碼纔會真正的執行
lazy適用於初始化開銷較大的場景
●代碼演示
package com.flyingAfish.baseTest object VariableDemo { def main(args: Array[String]): Unit = { val name:String = "fizz" //name = "jack ma" //錯誤,val修飾的變量不能被從新賦值 var money:Int = 8888 money = 565//var修飾的變量能夠從新賦值 val age = 18 //:Int 類型能夠省略,編譯器會自動推斷age的類型 //age = "fizz" //錯誤,由於scala是強類型 type str = String //type關鍵字能夠給類型起別名 val animal:str = "fish" //當val被聲明爲lazy時,初始化將被推遲,只有當這個變量真正被使用到的時候,變量的賦值代碼纔會真正的執行 //lazy適用於初始化開銷較大的場景 val msg1 = init() println("我是按順序執行的") println(msg1) println("===============") lazy val msg2 = init() println("我先於init方法執行") println(msg2) } //定義一個方法,輸出一句話並返回一個字符串 def init() ={ println("init方法執行了") "msg" } } /* init方法執行了 我是按順序執行的 msg =============== 我先於init方法執行 init方法執行了 msg */
scala提供多種定義字符串的方式,咱們能夠根據須要來選擇最方便的定義方式。
●雙引號
val/var 變量名 = "字符串"
●三引號
若是有大段的文本須要保存,就可使用三引號來定義字符串。例如:保存一大段的SQL語句。三個引號中間的全部字符串都將做爲字符串的值。
val/var 變量名 = """字符串1字符串2"""
●使用插值表達式
scala中,可使用插值表達式來定義字符串,有效避免大量字符串的拼接。
val/var 變量名 = s"${變量/表達式}字符串" val/var 變量名 = s"""${變量/表達式}字符串"""
●代碼演示
package com.flyingAfish.baseTest object StringDemo { def main(args: Array[String]): Unit = { val name = "fizz" val sql = """ |select * // | 豎條爲編譯器自動添加 |from table |where name = fizz """.stripMargin //.stripMargin 編譯器自動添加 val sql2 = s""" //s 爲編譯器自動添加 |select * |from table |where name = ${name} """.stripMargin println(name) println(sql) println(sql2) } } /* fizz select * from table where name = fizz select * from table where name = fizz */
●數值類型
Scala和Java同樣,有多種數值類型Byte、Char、Short、Int、Long、Float、Double類型和1個Boolean類型。
Boolean | true 或者 false |
---|---|
Byte | 8位, 有符號 |
Short | 16位, 有符號 |
Int | 32位, 有符號 |
Long | 64位, 有符號 |
Char | 16位, 無符號 |
Float | 32位, 單精度浮點數 |
Double | 64位, 雙精度浮點數 |
String | 其實就是由Char數組組成 |
●繼承體系
●Any
在scala中,全部的類,包括值類型,都最終繼承自一個統一的根類型Any,Any類是根節點
Any中定義了isInstanceOf、asInstanceOf方法,以及哈希方法等。AnyVal和AnyRef都擴展自Any類。
isInstanceOf:是否繼承自某類
asInstanceOf:強制類型轉換
●AnyVal-全部值類型的基類,全部的值都是類類型都是AnyVal的子類
- scala.Double
- scala.Float
- scala.Long
- scala.Int
- scala.Char
- scala.Short
- scala.Byte
上面是數字類型。
還包括scala.Unit 和 scala.Boolean 是非數字類型。
●AnyRef-是全部引用類型的基類。
除了值類型,全部其餘類型都繼承自AnyRef
●Null
是全部引用類型的子類型,Null類只有一個實例對象,null,相似於Java中的null引用。null能夠賦值給任意引用類型,可是不能賦值給值類型。
●Nothing
是全部類型的子類型。Nothing類型沒有實例。它對於泛型結構是有用處的,舉例:
空列表Nil的類型是List[Nothing],它是List[T]的子類型,T能夠是任何類。
Nothing能夠做爲沒有正常返回值的方法的返回類型,很是直觀的告訴你這個方法不會正常返回,並且因爲Nothing是其餘任意類型的子類,他還能跟要求返回值的方法兼容。
●Unit
用來標識過程,也就是沒有明確返回值的函數。
因而可知,Unit相似於Java裏的void。Unit只有一個對象實例(),這個實例也沒有實質的意義。
●注意
1.Scala並不刻意區分基本類型 和 引用類型,因此這些類型都是對象,能夠調用相對應的方法。
2.每一種數值類型都有對應的Rich類型,如RichInt、RichChar等,爲基本類型提供了更多的有用操做。(重要)
3.String直接使用的是java.lang.String類,另外在scala.collection.immutable.StringOps中還定義了更多的操做。在須要時String能隱式轉換爲StringOps,所以不須要任何額外的操做,String就可使用這些方法。
Scala中的+ - * / %等操做符的做用與Java同樣,位操做符 & | ^ >> <<也同樣。
●注意:
1.Scala中的操做符其實是方法
2.Scala中沒有++、--操做符,須要經過+=、-=來實現一樣的效果(由於++ -- 前置後置容易混淆)
3.+ - * / %是方法,那麼就能夠進行操做符重載,完成特殊的運算(也就是本身在類中定義+ - * / %方法表示特殊的運算)
●高級:
1)中置操做符,
//A操做符B 等同於 A.操做符(B) val a = 1 val b = 2 var c = a + b var d = a.+(b) //等同與上式
2)後置操做符,
A操做符 等同於 A.操做符,若是操做符定義的時候不帶()則調用時不能加括號
math.random
3)前置操做符,
+、-、!、~等操做符 A等同於 A.unary_操做符。
var b = true b = !b b = b.unary_! //等同與上式
4)賦值操做符,
A操做符=B 等同於 A=A操做符B
a += 1 a = a + 1 //等同與上式
●代碼演示
package com.flyingAfish.baseTest object OperatorDemo { def main(args: Array[String]): Unit = { var a = 1 var b = 2 val result = a + b println(result)//3 val result2 = a.+(b) //在Scala中運算符實際上是方法 println(result2)//3 //a++ //錯誤,在Scala中爲了不混淆,不支持++ -- a += 1 //a = a + 1 println(a)//2 }
定義變量時可使用 {} 包含一系列表達式,其中{}塊的最後一個表達式的值就是整個塊表達式的值。
●代碼演示
package com.flyingAfish.baseTest object E_BlockDemo { def main(args: Array[String]): Unit = { var a = 1 var b =2 var c = { a = a + b b = a + b var i = a + b i //注意:{}塊表達式的最後一行是整個表達式的值 } println(c)//8 } }
Scala條件表達式的語法和Java同樣,只是更加簡潔,且Scala中if else表達式是有返回值的
●注意:
Scala中沒有三元表達式
若是if或者else返回的類型不同,就返回Any類型
對於沒有返回值的,使用Unit,寫作(),至關於java中的void
●代碼演示
package com.flyingAfish.baseTest object ConditionDemo { def main(args: Array[String]): Unit = { val sex1 = "male" val sex2 = "female" //if表達式有返回值 val result1:String = if(sex1 == "male"){ "男" }else{ "女" } println(result1) val result2:String = if(sex1 == "male") "男" else "女" println(result2) //若是返回值類型不一致,返回Any val result3:Any = if(sex2 == "male"){ "男" }else{ 0 } println(result3) //()表示沒有返回值,即Unit,至關於Java中的void val result4:Unit = if(sex2 == "male"){ println("男") }else{ println("女") } println(result4)//() } }
在scala中,可使用for循環和while循環,但通常推薦使用for表達式,由於for表達式語法更簡潔
●簡單for循環:
for (變量 <- 表達式/數組/集合) {循環體}
for(i <- 1 to 10){println(i)} //循環打印1~10
●嵌套for循環
for (變量1 <- 表達式/數組/集合; 變量2 <- 表達式/數組/集合) {循環體}
for(i <- 1 to 9; j <- 1 to 9){ if(i >= j ) print(s"${j} * ${i} = ${j*i}") if(j == 9) println() }
●守衛
for表達式中,能夠添加if判斷語句,這個if判斷就稱之爲守衛。咱們可使用守衛讓for表達式更簡潔。
for(i <- 表達式/數組/集合 if 表達式) {循環體}
for(i <- 1 to 10 if i % 3 == 0) println(i) //3,6,9
●for推導式(有返回值)
在for循環體中,可使用yield表達式構建出一個集合,咱們把使用yield的for表達式稱之爲推導式
便可以使用for推導式生成一個新的集合(一組數據)
//該for表達式會構建出一個集合 val res = for(i <- 1 to 10) yield i * 10 //10,20,30,40...
●注意:
while、for語句自己沒有值,即整個while語句的結果是Unit類型的()
var n = 1; val result:unit = while(n <= 10){ n += 1 } println(result) println(n)
●代碼演示
package com.flyingAfish.baseTest object LoopDemo { def main(args: Array[String]): Unit = { //1 to 10 ===> [1,10] val res1 = 1 to 10 //Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) //1 until 10 ===> [1,10) val res2 = 1 until 10 //Range(1, 2, 3, 4, 5, 6, 7, 8, 9) //1 to 10 ===> [1,10],步長爲2 val res3 = 1 to 10 by 2 //Range(1, 3, 5, 7, 9) println(res1) println(res2) println(res3) //1.簡單for循環 for(i <- 1 to 10) println(i) println("===========分割線==========") //2.嵌套for循環--傳統寫法 for(i <- 1 to 9){ for(j <- 1 to 9){ if(i >= j){ print(s"${j} * ${i} = ${j * i} \t") } } println() } println("===========分割線==========") //2.嵌套for循環--Scala騷氣寫法 for(i <- 1 to 9;j <- 1 to 9){ if(i >= j) print(s"${j} * ${i} = ${j * i} \t") if(j == 9) println() } println("===========分割線==========") //3.守衛 //需求打印1~10中3的倍數 for(i <- 1 to 10){ if(i % 3 == 0) println(i) } println("===========分割線==========") for(i <- 1 to 10 if(i % 3 == 0)) println(i) println("===========分割線==========") //4.for推導式 //需求把1~10中的每個數擴大10倍造成一個新的集合 //使用yield關鍵字能夠生成一個新的集合 val col = for(i <- 1 to 10) yield i * 10 println(col)//Vector(10, 20, 30, 40, 50, 60, 70, 80, 90, 100) println("===========分割線==========") //5.注意:while循環沒有返回值 var n =1 val result = while (n <= 100){ n += 1 n } println(n)//101 println(result)//() } }
def 方法名(參數名1: 參數類型1, 參數名2: 參數類型2) : 返回類型 = {方法體}
●語法細節
\1. 方法的返回值類型和return能夠不寫,編譯器能夠自動推斷出來
\3. 若是方法沒有返回值,返回Unit類型(相似於void,也能夠不寫)
\4. 返回值類型有多種狀況則返回Any
\5. 帶有默認值參數的方法,調用時,能夠給定新值,也可使用默認值
\6. 能夠經過參數名來指定傳遞給哪個參數,這樣傳遞參數時就能夠不按照順序傳遞
\7. 方法沒有參數,調用時能夠省略(),若是定義時()省略,調用時則必須省略
\8. 可變參數使用 變量名: 類型* (相似Java的...)
●代碼演示
package com.flyingAfish.baseTest object MethodDemo { def main(args: Array[String]): Unit = { val result: Int = factorial(3) println(result)//6 println(noReturnValue())//() //val resutl2: Int = haveDefaultParam(b=2)//102 //val resutl3: Int = haveDefaultParam(a=1,b=2)//3 //val resutl4: Int = haveDefaultParam(1,2)//3 val resutl5: Int = haveDefaultParam(b=2,a=1)//3 //println(resutl2) //println(resutl3) //println(resutl4) println(resutl5) noParam val sum: Int = multiParam(1,2,3,4,5)//15 println(sum) } //def 方法名(參數名1:參數類型,參數名1:參數類型):返回值類型 = {方法體} //1.方法的返回值類型和return能夠不寫,編譯器能夠自動推斷出來 def omitReturnValue() ={ 1 } //2.對於遞歸方法,必須指定返回類型 //需求:求n的階乘 ==> 10的階乘=1*2*3...*10 == 10 * 9 * 8 ..... def factorial(n:Int):Int = { if (n == 1){ 1 }else{ n * factorial(n-1) } } //3.若是方法沒有返回值,返回Unit類型(相似於void,也能夠不寫) def noReturnValue():Unit={ println("m3") } //4.返回值類型有多種狀況則返回Any或者不寫 val sex = "male" def multiReturnValue():Any={ if (sex == "male"){ "男" }else{ 0 } } //5.帶有默認值參數的方法,調用時,能夠給定新值,也可使用默認值 //6.能夠經過參數名來指定傳遞給哪個參數,這樣傳遞參數時就能夠不按照順序傳遞 def haveDefaultParam(a:Int=100,b:Int):Int={ println("a="+a) println("b="+b) a + b } //7.方法沒有參數,調用時能夠省略(),若是定義時()省略,調用時則必須省略 def noParam={ println("m7") } //8.可變參使用 變量名:類型* (相似Java的...) //定義了一個方法能夠傳遞多個int值,並返回他們的和 def multiParam(args:Int*):Int={ var sum = 0 for (i <- args){ sum +=i } sum } }
●完整語法:
val函數名稱 :(參數類型)=>函數返回值類型 = (參數名稱:參數類型)=>函數體
val sum:(Int,Int)=>Int = (a:Int,b:Int)=>{a + b}
●簡寫語法:
val函數名稱 = (參數名稱:參數類型) => 函數體
val max = (a:Int,b:Int)=>{ if(a > b) a else b }
●符號解釋
= 表示將右邊的函數 賦給 左邊的變量
=> 左面表示輸入參數名稱和類型,右邊表示函數的實現和返回值類型
●方法:
和以前學習Java時理解的方法同樣,是封裝了完成某些功能的代碼塊,所屬於某一個類或對象
●函數:
在Scala中,函數是頭等公民,函數是一個對象,那麼既然是對象的話,函數就能夠賦值給變量 或者 看成參數被傳遞,還能夠 使用函數打點調用方法
Scala中函數繼承自FuctionN,帶有一個參數的函數的類型是function1,帶有兩個是function2,以此類推
●證實函數是對象
●函數是對象,能夠打點調方法
package com.flyingAfish.baseTest object FunctionDemo { def main(args: Array[String]): Unit = { //val函數名稱 = (參數名稱:參數類型) => 函數體 val add1 = (a:Int) => {a } val add2 = (a:Int,b:Int) => {a + b} val add3: (Int, Int, Int) => Int = (a:Int, b:Int, c:Int) => {a + b + c} println(add1)//<function1> println(add2)//<function2> println(add3)//<function3> //結論:函數是對象,有N個參數打印的時候就是functionN val str: String = add1.toString()//函數是對象,因此能夠調用方法 println(str)//<function1> //函數通常用法 println(add2(3,2))//5 } }
●函數能夠賦值給變量並將能夠看成參數進行傳遞
定義一個函數,接收兩個參數,返回兩個數的和
定義一個方法,接收兩個參數和一個函數,並在方法體中調用函數,將兩個參數傳遞給函數
package com.flyingAfish.baseTest object FunctionDemo { def main(args: Array[String]): Unit = { //函數能夠賦值給變量並將能夠看成參數進行傳遞 //定義一個函數,接收兩個參數,返回兩個數的和 val add = (a:Int,b:Int) => a + b //證實了函數是對象,且函數能夠賦值給變量 val result1: Int = operator(1,2,add) //證實了函數是對象,且函數能夠看成參數進行傳遞 println(result1)//3 //函數的好處: //能夠將咱們要進行的操做進行傳遞!!! //也就是函數式編程的核心思想:行爲參數化!!! val result2: Int = operator(1,2, (a,b)=> a*b) println(result2) println("=======================") //再來體會一下:行爲參數化!!! //val list = List(1,2,3,4,5) val list = 1 to 5 //val f = (i:Int) => println(i) //list.foreach((i:Int) => println(i)) //list.foreach(i => println(i)) //list.foreach(println(_)) list.foreach(println) } //定義一個方法,接收兩個參數和一個函數,並在方法體中調用函數,將兩個參數傳遞給函數 def operator(a:Int,b:Int,fun:(Int,Int)=>Int) ={ fun(a,b) } }
●方法能夠轉換成函數
證實方法無返回值也能夠調用
Java裏面方法無返回值不能調用
package com.flyingAfish.baseTest object I_FunctionDemo4 { def main(args: Array[String]): Unit = { println(fizz()) //() 證實函數五返回值也能夠條用,打印的是空括號() println(fizz _) //下劃線 _能夠將方法變成函數 //<function0> } def fizz() = { } }
●定義方法:
def 方法名(參數名1: 參數類型1, 參數名2: 參數類型2) : 返回類型 = {方法體}
●定義方法簡寫法:
def 方法名(參數名1: 參數類型1, 參數名2: 參數類型2) = {方法體}
def 方法名 = {方法體}
●定義函數完整語法:
val函數名稱 :(參數類型)=>函數返回值類型 = (參數名稱:參數類型)=>函數體
●定義函數簡寫語法:
val函數名名稱 = (參數名稱:參數類型) => 函數體
●注意:
嚴格的來講,函數與方法是不一樣的東西。定義方式上也有不少的區別
可是在Scala中,函數自己是對象,方法能夠經過下劃線_轉換爲函數。
結論:在Scala中
方法能夠轉換爲函數,函數本質上就是對象
函數式編程的核心思想、靈魂所在:行爲參數化!
●集合分類-按照數據結構特色分
Scala的集合都擴展自Iterable特質(先理解爲接口)
有三大類:Seq序列(List)、Set、Map映射
●集合分類-按照可變和不可變分(注意:這裏的可變和不可變指的是集合的內容和長度,和以前的var/val有區別)
大部分的集合Scala都同時提供了可變和不可變的版本。
開發時建議Scala優先採用不可變集合(默認即爲不可變),知足不了需求是再使用可變集合
●可變集合和不可變集合相應的包爲:
不可變集合:scala.collection.immutable (默認)
可變集合: scala.collection.mutable
●注意
val和可變不可變
var和val指的是:變量可否被從新賦值
集合可不可變指的是:集合長度或內容可不可變
對於數組:
不可變數組Array:長度不可變,元素可變(定長數組)
可變數組ArrayBuffer:長度和裏面的元素均可變(變長數組)(注意:Java裏面數組長度不可變)
對於其餘集合:
不可變集合immutable:長度和內容都不可變,若是調用添加或者刪除方法,會產生新的集合,原集合不變
可變集合mutable:長度和內容均可變
總結:
開中優先使用不可變,若是知足不了需求再使用可變
●不可變集合(immutable )繼承層次:
●可變集合(mutable)繼承層次:
●不可變/定長數組:
val/var 變量名= new Array[T](數組長度)//scala.collection.immutable包下,不須要導包,默認就是 val/var 變量名 = Array(元素1, 元素2, 元素3...)
●可變/變長數組:
val/var 變量名 = ArrayBuffer[T]() //須要手動導入import scala.collection.mutable.ArrayBuffer包 val/var 變量名 = ArrayBuffer(元素1, 元素2, 元素3...)
●數組操做
指定分隔符 mkString
將數組轉換成數組緩衝 toBuffer(打印Buffer能夠看到數組內容)
根據索引獲取元素 ()
添加元素 +=
刪除元素 -=
追加一個數組到變長數組 ++=
往指定角標插入元素 insert
刪除指定角標的元素 remove
定長=>>變長 toBuffer
變長=>>定長 toArray
多維數組 Array.ofDimDouble
●遍歷數組
1.能夠for循環直接遍歷數組
2.能夠遍歷下標再根據下標獲取元素
3.回憶一下生成指定範圍的序列
0 to n 生成[0,n]
0 until n 生成[0,n)
●數組其餘經常使用方法
在Scala中,數組上的某些方法對數組進行相應的操做很是方便!
sum求和
max求最大值
min求最小值
sorted排序
reverse反轉
●代碼演示
package com.flyingAfish.baseTest import scala.collection.mutable object ArrayDemo { def main(args: Array[String]): Unit = { val arr: Array[Int] = Array(5,6,7,1,2,3,4,8,9)//不可變 //不可變==>可變 val arr2: mutable.Buffer[Int] = arr.toBuffer //可變==>不可變 val arr3: Array[Int] = arr2.toArray //遍歷 for(i <- arr) println(i) println("====================") //arr.foreach((i:Int)=>println(i)) //arr.foreach(i=>println(i)) //arr.foreach(println(_)) arr.foreach(println)//行爲參數化 println("====================") //逆序 for(i <- arr.reverse) println(i) println("====================") //經過索引遍歷 for(i <- 0 until arr.length) println(arr(i)) //統計 println(arr.sum) println(arr.max) println(arr.min) println(arr.reverse.mkString(",")) println(arr.sorted.mkString(","))//按照默認的排序規則排序-升序 println(arr.sortBy((i:Int) => -i).mkString(",")) //降序 println(arr.sortWith((x:Int,y:Int) => x > y).mkString(","))//降序 } }
元組也是能夠理解爲一個容器,能夠用來存放各類相同或不一樣類型的數據。例如:姓名,年齡,性別,出生年月。
元組的元素是不可變的。
●建立元組
使用括號來定義元組
val/var 元組 = (元素1, 元素2, 元素3....) val animal = ("fish","cat","dog") val world = ("fizz",34,animal,34.43)
使用箭頭來定義元組(元組只有兩個元素)
val/var 元組 = 元素1->元素2 //對偶/二元組是最簡單的元組(k,v) val animal: (String, String) = ("fizz", "dgo") val dog: (String, Int) = "god" -> 3
●獲取元組中的值
//使用下劃線加腳標 ,例如 元組名._1 元組名._2 元組名._3 val animal: (String, String) = ("fizz", "dgo") val dog: (String, Int) = "dog" -> 3 val name: String = animal._1 val age: Int = dog._2
注意:元組中的元素腳標是從1開始的
●將對偶(二元組)組成的數組轉換成映射(映射就至關於Java中的Map,後面會講)
將對偶/二元組的集合轉換成映射:
調用其toMap 方法
●遍歷
能夠調用元組的productIterator方法獲取迭代器對象進行遍歷
●代碼演示
package com.flyingAfish.baseTest object TupleDemo { def main(args: Array[String]): Unit = { //使用括號來定義元組 //val/var 元組 = (元素1, 元素2, 元素3....) val t1: (String, Double, Int) = ("hadoop",3.14,110) //元組裏能夠存放不一樣類型的元素 //使用箭頭來定義元組(元組只有兩個元素) //val/var 元組 = 元素1->元素2 //對偶/二元組是最簡單的元組(k,v) val t2: (String, Int) = "age"->18 val t3 = ("age",18) println(t1) println(t2) println(t3) println(t1.getClass) println(t2.getClass) println(t3.getClass) //獲取元素 println(t1._1) println(t1._2) println(t1._3) println("============") //val iterator: Iterator[Any] = t1.productIterator for(i <- t1.productIterator) println(i) //將二元組組成的集合轉成map val ts = Array(("jack",60),("tom",70),("rose",80)) val map: Map[String, Int] = ts.toMap println(map)//Map(jack -> 60, tom -> 70, rose -> 80) } }
●高能預警
List操做的API方法和符號特別特別多,不用刻意去記,後續學習中會使用一些常見的,用的多了就掌握了!
●List介紹
列表是scala中最重要的、也是最經常使用的數據結構。在scala中,也有兩種列表,一種是不可變列表、另外一種是可變列表
但都具有如下性質:
能夠保存重複的值
有前後順序
●不可變列表(默認)
import scala.collection.immutable._
建立方式1.使用List(元素1, 元素2, 元素3, ...)來建立一個不可變列表
val/var 變量名 = List(元素1, 元素2, 元素3...) val strings: List[String] = List("book","subject","car") val book: List[Any] = List("English", 32, "chinese", 300)
建立方式2.使用::方法建立一個不可變列表
val/var 變量名 = 元素1 :: 元素2 :: Nil val money: List[Int] = 34 :: 34 :: 344 :: Nil
注意:
使用::拼接方式來建立列表,必須在最後添加一個Nil表示空列表
●可變列表
import scala.collection.mutable._
建立方式1.使用ListBuffer元素類型建立空的可變列表
val/var 變量名 = ListBuffer[Int]() val fizz: ListBuffer[Int] = ListBuffer[Int]()
建立方式2.使用ListBuffer(元素1, 元素2, 元素3...)建立可變列表
val/var 變量名 = ListBuffer(元素1,元素2,元素3...) val personName: ListBuffer[Any] = ListBuffer("kashke",34,"wangzida")
●head和tail
在Scala中列表要麼爲Nil(Nil表示空列表)
要麼是一個head元素加上一個tail列表。
//head爲列表第一個元素,tail爲列表除第一個元素外的元素列表 val list1 = List(1,2,3,4,5) println(list1.head)//1 println(list1.tail)//List(2, 3, 4, 5) val list = List(1) println(list)//List(1) println(list.head)//1 println(list.tail)//List()
●::操做符
:: 操做符是將給定的頭和尾建立一個新的列表,原列表不變 :: 操做符是右結合的,如1 :: 5 :: 2 :: Nil至關於 1 :: (5 :: (2 :: Nil)) ==> List(1,5,2)
●可變列表操做
獲取/更改元素(使用括號訪問(索引值)) 添加元素(+=) 追加一個列表(++=) 刪除元素(-=) 轉換爲List(toList) 轉換爲Array(toArray)
●擴展:list其餘操做符(瞭解)
:: (x: A): List[A] 在列表的頭部添加一個元素或列表 +: (elem: A): List[A] 在列表的頭部添加一個元素 :+ (elem: A): List[A] 在列表的尾部添加一個元素 ++ [B](that: GenTraversableOnce[B]): List[B] 從列表的尾部添加另一個列表 ::: (prefix: List[A]): List[A] 在列表的頭部添加另一個列表
●擴展:等價操做(瞭解)
val left = List(1,2,3) val right = List(4,5,6) //如下操做等價 left ++ right // List(1,2,3,4,5,6) right.:::(left) // List(1,2,3,4,5,6) //如下操做等價 0 +: left //List(0,1,2,3) left.+:(0) //List(0,1,2,3) //如下操做等價 left :+ 4 //List(1,2,3,4) left.:+(4) //List(1,2,3,4) //如下操做等價 0 :: left //List(0,1,2,3) left.::(0) //List(0,1,2,3)
●代碼演示
package com.flyingAfish.baseTest object ListDemo { def main(args: Array[String]): Unit = { //●不可變列表 //val/var 變量名 = List(元素1, 元素2, 元素3...) val list1 = List(1,2,3,4,5) //val/var 變量名 = 元素1 :: 元素2 :: Nil val list2 = 1::2::Nil //List(1,2) //●可變列表 //val/var 變量名 = ListBuffer[Int]() import scala.collection.mutable.ListBuffer val list3 = ListBuffer[Int]() //val/var 變量名 = ListBuffer(元素1,元素2,元素3...) val list4 = ListBuffer(1,2,3,4) list3.append(1,2,3) println(list1) println(list2) println(list3)//ListBuffer(1, 2, 3) println(list4) //List(1, 2, 3, 4, 5) //List(1, 2) //ListBuffer(1, 2, 3) //ListBuffer(1, 2, 3, 4) println(list1.head)//1 println(list1.tail)//List(2, 3, 4, 5) val list = List(1) println(list)//List(1) println(list.head)//1 println(list.tail)//List() println("============") list3.remove(1)//根據索引刪除 println(list3)//ListBuffer(1, 3) list3 += 4 list3 -= 1 val list5 = list3.toList val list6 = list3.toArray val list7 = 0 +: list3 println(list7)//ListBuffer(0, 3, 4) list7 //遍歷 for(i <- list3) println(i) list3.foreach(println) } }
●說明
隊列數據存取符合先進先出的策略
有 scala.collection.mutable.Queue 和 scala.collection.immutable.Queue
通常來講咱們在開發中隊列一般使用可變隊列(特殊),其餘都推薦使用不可變
●常見操做
enqueue入隊/+=追加
dequeue出隊
●代碼演示
package com.flyingAfish.baseTest import scala.collection.mutable object DueueDemo { def main(args: Array[String]): Unit = { //隊列在開發中通常使用可變隊列 val q = mutable.Queue[Int]() q.enqueue(1) q.enqueue(2) q.enqueue(3) q += 4 q.+=(5) println(q)//Queue(1, 2, 3, 4 , 5) val i: Int = q.dequeue() println(i)//1 } }
●Set說明
Set表明一個沒有重複元素的無序集合;即沒法加入重複元素且不保證插入順序的。
●不可變Set(默認)
import scala.collection.immutable._
1.建立一個空的不可變集,語法格式:
val/var 變量名 = Set[類型]() val movie = Set[String]()
2.給定元素來建立一個不可變集,語法格式:
val/var 變量名 = Set(元素1, 元素2, 元素3...) val fresh = Set("apple","pear","apricot")
●可變Set
import scala.collection.mutable._
格式相同,導包不一樣
●Set操做
方法 | 描述 |
---|---|
def +(elem: A): Set[A] | 爲集合添加新元素,並建立一個新的集合,除非元素已存在 |
def -(elem: A): Set[A] | 移除集合中的元素,並建立一個新的集合 |
def contains(elem: A): Boolean | 若是元素在集合中存在,返回 true,不然返回 false。 |
def &(that: Set[A]): Set[A] | 返回兩個集合的交集 |
def &~(that: Set[A]): Set[A] | 返回兩個集合的差集 |
def ++(elems: A): Set[A] | 合併兩個集合 |
●代碼演示
package com.flyingAfish.baseTest object SetDemo { def main(args: Array[String]): Unit = { //●不可變Set(默認) //val/var 變量名 = Set(元素1, 元素2, 元素3...) val set1 = Set(1,2,3,4,5,6,7) //●可變Set //格式相同,導包不一樣 //val/var 變量名 = Set[類型]() import scala.collection.mutable._ val set2 = Set[Int]() set2.add(1) set2.add(2) set2.add(3) val set3 = set2 + 4 val set4 = set2 - 1 set2.remove(2) println(set2)//Set(1, 3) println(set3)//Set(1, 2, 3, 4) println(set4)//Set(2, 3) val set5 = set2 ++ set3 //並集 println(set5)//Set(1, 2, 3, 4) val set6 = set3 & set2 println(set6)//Set(1, 3)//交集 val set7 = set3 &~ set2//差集 println(set7)//Set(2, 4) //遍歷和其餘集合同樣 } }
●說明
在Scala中,把哈希表這種數據結構叫作映射。類比Java的map集合
●不可變Map
import scala.collection.immutable.Map
格式一:使用箭頭
val/var map = Map(鍵->值, 鍵->值, 鍵->值...) // 推薦,可讀性更好 val hero = Map("fish"->"潮汐海靈","zeus"->"宙斯","baiqi"->"白起")
格式二:利用元組
val/var map = Map((鍵, 值), (鍵, 值), (鍵, 值), (鍵, 值)...) val subject = Map(("math","數學"),("English","英語"),("physics","物理"))
●可變Map
import scala.collection.mutable.Map
格式相同,導包不一樣
●獲取值
map(鍵) map.get(鍵) map.getOrElse(鍵,默認值)//根據鍵取值,若是取到了則返回,沒取到返回指定的默認值
●修改值
map(鍵)=值
●增長值
map.put(鍵,值)
●代碼演示
package cn.fizz.collection object MapDemo { def main(args: Array[String]): Unit = { //●不可變Map //●可變Map //格式相同,導包不一樣 import scala.collection.mutable._ //格式一:使用箭頭val/var map = Map(鍵->值, 鍵->值, 鍵->值...) // 推薦,可讀性更好 val map1 = Map("tom"->60,"rose"->70,"jack"->80,"zhaosi"->100) //格式二:利用元組val/var map = Map((鍵, 值), (鍵, 值), (鍵, 值), (鍵, 值)...) val map2 = Map(("tom",60),("rose",70),("jack",80),("zhaosi",100)) map1.put("lily",90) map1.remove("tom") println(map1) println(map2) //根據key取值 //Option是None和Some的父類 //None表示空的,什麼都沒有 //Some表示裏面有一個元素,在使用get就能夠取出來 val op: Option[Int] = map1.get("zhaosi") println(op.get)//100 //直接使用get方法很差,若是沒有指定的key,繼續操做可能會報錯 //val op2: Option[Int] = map1.get("zaosi") //println(op2.get) val v: Int = map1.getOrElse("zaosi",0) println(v)//0 val v2: Int = map1.getOrElse("zhaosi",0) println(v2)//100 println("==========================") //遍歷 //1.經過key for(k <- map1.keySet) println(map1(k)) println("==========================") //2.直接遍歷value for(v <- map1.values) println(v) println("==========================") //3.經過元組 for((k,v) <- map1) println(k+":"+v) println("==========================") //4.函數式的遍歷+模式匹配 map1.foreach{ case (k,v) => println(k+":"+v) } } } -------------------------------------------------------------------- -----------------------java版本------------------------------------- -------------------------------------------------------------------- import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set; public class MapDemo { public static void main(String[] args){ Map<String, Integer> map = new HashMap<>(); map.put("k1",1); map.put("k2",2); map.put("k3",3); map.put("k4",4); Set<String> set = map.keySet(); for (String k : set) { System.out.println(map.get(k)); } Collection<Integer> values = map.values(); for (Integer value : values) { System.out.println(value); } //開發的時候建議使用entrySet //由於entrySet拿出來的就是全部的kv,不須要在根據k去找v!!! Set<Map.Entry<String, Integer>> entries = map.entrySet(); for (Map.Entry<String, Integer> entry : entries) { System.out.println(entry.getKey() + ":"+entry.getValue()); } } }