第十章 資料結構(上)-集合10.1 資料結構特點10.1.1 Scala 集合基本介紹10.1.2 可變集合和不可變集合舉例10.2 Scala 不可變集合繼承層次一覽圖10.2.1 圖10.2.2 小結10.3 Scala 可變集合繼承層次一覽圖10.3.1 圖10.3.2 小結10.4 陣列-定長陣列(宣告泛型)10.4.1 第一種方式定義陣列10.4.2 第二種方式定義陣列10.5 陣列-變長陣列(宣告泛型)10.5.1 變長陣列分析小結10.5.2 定長陣列與變長陣列的轉換10.5.3 多維陣列的定義和使用10.6 陣列-Scala 陣列與 Java 的 List 的互轉10.6.1 Scala 陣列轉 Java 的 List10.6.2 Java 的 List 轉 Scala 陣列(mutable.Buffer)10.6.3 補充一個多型的知識點(使用 trait 來實現引數多型)10.7 元組 Tuple10.7.1 元祖的基本介紹+元祖的建立10.7.2 元組的建立-程式碼小結10.7.3 元組資料的訪問+遍歷10.8 列表 List10.8.1 建立 List + List 元素的訪問10.8.2 建立 List 的應用案例小結10.8.3 List 元素的追加10.8.4 ListBuffer10.9 佇列 Queue10.9.1 佇列的建立+追加資料10.9.2 刪除和加入佇列元素+返回佇列元素10.10 對映 Map10.10.1 Map 的基本介紹10.10.2 Map 的建立10.10.3 Map 的取值10.10.4 可變 Map 的修改、新增和刪除10.10.5 Map 的遍歷10.11 集 Set10.11.1 Set 基本介紹10.11.2 Set 的建立10.11.3 Set 的取值10.11.4 可變 Set 的修改、新增和刪除10.11.5 Set 的遍歷10.12 Set 的更多操作
第十章 資料結構(上)-集合
10.1 資料結構特點
10.1.1 Scala 集合基本介紹
10.1.2 可變集合和不可變集合舉例
示例程式碼如下:
package com.atguigu.chapter10.test;
import java.util.ArrayList;
public class JavaCollectionDemo {
public static void main(String[] args) {
// 不可變集合類似 java 的陣列
int[] nums = new int[3];
nums[2] = 11;
// nums[3] = 90; // 陣列越界
String[] names = {"bj", "sh"};
System.out.println(nums + " " + names); // [I@12a3a380 [Ljava.lang.String;@29453f44
// 可變集合舉例
ArrayList al = new ArrayList<String>();
al.add("zs");
al.add("zs2");
System.out.println(al + " " + al.hashCode()); // [zs, zs2] 242625
al.add("zs3");
System.out.println(al + " " + al.hashCode()); // [zs, zs2, zs3] 7642233
}
}
輸出結果如下:
[I@12a3a380 [Ljava.lang.String;@29453f44
[zs, zs2] 242625
[zs, zs2, zs3] 7642233
10.2 Scala 不可變集合繼承層次一覽圖
10.2.1 圖
10.2.2 小結
1、Set、Map 是 Java 中也有的集合。
2、Seq 是 Java 中沒有的,我們發現 List 歸屬到 Seq 了,因此這裡的 List 就和 java 不是同一個概念了。
3、我們前面的 for 迴圈有一個 1 to 3,就是 IndexedSeq 下的 Vector。
4、String 也是屬於 IndexeSeq。
5、我們發現經典的資料結構,比如Queue 和 Stack 被歸屬到 LinearSeq。
6、大家注意 Scala 中的 Map 體系有一個SortedMap,說明 Scala 的 Map 可以支援排序。
7、IndexSeq 和 LinearSeq 的區別
IndexSeq 是通過索引來查詢和定位,因此速度快,比如 String 就是一個索引集合,通過索引即可定位。
LineaSeq 是線型的,即有頭尾的概念,這種資料結構一般是通過遍歷來查詢,它的價值在於應用到一些具體的應用場景(比如:電商網站,大資料推薦系統:最近瀏覽的10個商品)。
10.3 Scala 可變集合繼承層次一覽圖
10.3.1 圖
10.3.2 小結
1、Scala 可變集合中比不可變集合豐富。
2、在 Seq 集合中,增加了 Buffer 集合,將來開發中,我們常用的有 ArrayBuffer 和 ListBuffer。
3、如果涉及到執行緒安全可以選擇 Syn.. 開頭的集合。
4、其他的小結參考不可變集合。
10.4 陣列-定長陣列(宣告泛型)
10.4.1 第一種方式定義陣列
說明:這裡的陣列等同於 Java 中的陣列,中括號的型別就是陣列的型別。
val arr1 = new Array[Int](10)
// 賦值,集合元素採用小括號訪問
arr1(1) = 7
示例程式碼如下:
package com.atguigu.chapter10.array
/**
* 第一種方式定義陣列
* 說明:這裡的陣列等同於 Java 中的陣列,中括號的型別就是陣列的型別。
*/
object ArrayDemo01 {
def main(args: Array[String]): Unit = {
// 明
// 1. 建立了一個 Array 物件
// 2. [Int] 表示泛型,即該陣列中,只能存放 Int
// 3. [Any] 表示該陣列可以存放任意型別
// 4. 在沒有賦值情況下,各個元素的值玩為0
// 5. arr01(3) = 10 表示修改第4個元素的值
val arr01 = new Array[Int](4) // 底層 int[] arr01 = new int[4]
println(arr01.length) // 4
println("arr01(0)=" + arr01(0)) // 0
//資料的遍歷
for (i <- arr01) {
println(i)
}
println("----------")
arr01(3) = 10
for (i <- arr01) {
println(i)
}
}
}
輸出結果如下:
4
arr01(0)=0
0
0
0
0
----------
0
0
0
10
10.4.2 第二種方式定義陣列
說明:在定義陣列時,直接賦值。
// 使用 apply 方法建立陣列物件
val arr1 = Array(1, 2)
示例程式碼如下:
package com.atguigu.chapter10.array
/**
* 第二種方式定義陣列
* 說明:在定義陣列時,直接賦值。
*/
object ArrayDemo02 {
def main(args: Array[String]): Unit = {
// 說明
// 1. 使用的是 object Array 的 apply 方法
// 2. 直接初始化陣列,因為你給了整數和字串, 這個陣列的泛型就是 Any 了
// 3. 遍歷方式一樣
var arr02 = Array(1, 3, "xxx")
arr02(1) = "xx"
for (i <- arr02) {
println(i)
}
// 可以使用我們傳統的方式遍歷,使用下標的方式遍歷
for (index <- 0 until arr02.length) {
printf("arr02[%d]=%s", index, arr02(index) + "\t")
}
}
}
輸出結果如下:
1
xx
xxx
arr02[0]=1 arr02[1]=xx arr02[2]=xxx
10.5 陣列-變長陣列(宣告泛型)
說明:
// 定義/宣告
val arr2 = ArrayBuffer[Int]()
// 追加值/元素
arr2.append(7)
// 重新賦值
arr2(0) = 7
示例程式碼如下:
package com.atguigu.chapter10.array
import scala.collection.mutable.ArrayBuffer
object ArrayBufferDemo01 {
def main(args: Array[String]): Unit = {
// 建立 ArrayBuffer
val arr01 = ArrayBuffer[Any](3, 2, 5)
// 訪問,查詢
// 通過下標訪問元素
println("arr01(1)=" + arr01(1)) // arr01(1) = 2
// 遍歷
for (i <- arr01) {
println(i)
}
println(arr01.length) // 3
println("arr01.hash=" + arr01.hashCode()) // arr01.hash=110266112
// 修改 [修改值,動態增加]
// 使用 append 追加資料,append 支援可變引數
// 可以理解成 java 的陣列的擴容
arr01.append(90.0, 13) // (3, 2, 5, 90.0, 13) append 底層重新 new 出一個陣列,然後底層把新的地址值重新賦給 arr01
println("arr01.hash=" + arr01.hashCode()) // arr01.hash=-70025354
println("====================")
arr01(1) = 89 // 修改 (3, 89, 5, 90.0, 13)
println("----------")
for (i <- arr01) {
println(i)
}
// 刪除
// 刪除,是根據下標來說
arr01.remove(0) // (89, 5, 90.0, 13) // arr01.hash=-1775231646
println("arr01.hash=" + arr01.hashCode())
println("----------刪除後的元素遍歷----------")
for (i <- arr01) {
println(i)
}
println("最新的長度=" + arr01.length) // 4
}
}
輸出結果如下:
arr01(1)=2
3
2
5
3
arr01.hash=110266112
arr01.hash=-70025354
====================
----------
3
89
5
90.0
13
arr01.hash=-1775231646
----------刪除後的元素遍歷----------
89
5
90.0
13
最新的長度=4
10.5.1 變長陣列分析小結
10.5.2 定長陣列與變長陣列的轉換
示例程式碼如下:
package com.atguigu.chapter10.array
import scala.collection.mutable.ArrayBuffer
object Array22ArrayBuffer {
def main(args: Array[String]): Unit = {
val arr2 = ArrayBuffer[Int]()
// 追加值
arr2.append(1, 2, 3)
println(arr2)
// 說明
// 1. arr2.toArray 呼叫 arr2 的方法 toArray
// 2. 將 ArrayBuffer --> Array
// 3. arr2 本身沒有任何變化
val newArr = arr2.toArray
println(newArr)
// 說明
// 1. newArr.toBuffer 是把 Array --> ArrayBuffer
// 2. 底層的實現
/*
override def toBuffer[A1 >: A]: mutable.Buffer[A1] = {
val result = new mutable.ArrayBuffer[A1](size)
copyToBuffer(result)
result
}
*/
// 3. newArr 本身沒變化
val newArr2 = newArr.toBuffer
newArr2.append(123)
println(newArr2)
}
}
輸出結果如下:
ArrayBuffer(1, 2, 3)
[I@7a79be86
newArr2.hash=387518613
newArr2.hash=-1552340494
ArrayBuffer(1, 2, 3, 123)
10.5.3 多維陣列的定義和使用
說明
// 定義
val arr = Array.ofDim[Double](3, 4)
// 說明:二維陣列中有三個一維陣列,每個一維陣列中有四個元素
// 賦值
arr(1)(1) = 11.11
示例程式碼如下:
package com.atguigu.chapter10.array
object MultiplyArray {
def main(args: Array[String]): Unit = {
// 建立
val arr = Array.ofDim[Int](3, 4)
// 遍歷
for (item <- arr) { // 取出二維陣列的各個元素(是一維陣列)
for (item2 <- item) { // 元素(是一維陣列),遍歷一維陣列
print(item2 + "\t")
}
println()
}
// 指定取出
println(arr(1)(1)) // 0
// 修改值
arr(1)(1) = 10
//遍歷
println("====================")
for (item <- arr) { // 取出二維陣列的各個元素(是一維陣列)
for (item2 <- item) { // 元素(是一維陣列),遍歷一維陣列
print(item2 + "\t")
}
println()
}
// 使用傳統的下標的方式來進行遍歷
println("====================")
for (i <- 0 to arr.length - 1) {
for (j <- 0 to arr(i).length - 1) {
printf("arr[%d][%d]=%d\t", i, j, arr(i)(j))
}
println()
}
}
}
輸出結果如下:
0 0 0 0
0 0 0 0
0 0 0 0
0
====================
0 0 0 0
0 10 0 0
0 0 0 0
====================
arr[0][0]=0 arr[0][1]=0 arr[0][2]=0 arr[0][3]=0
arr[1][0]=0 arr[1][1]=10 arr[1][2]=0 arr[1][3]=0
arr[2][0]=0 arr[2][1]=0 arr[2][2]=0 arr[2][3]=0
10.6 陣列-Scala 陣列與 Java 的 List 的互轉
10.6.1 Scala 陣列轉 Java 的 List
在專案開發中,有時我們需要將 Scala 陣列轉成 Java 陣列,看下面案例:
示例程式碼如下:
package com.atguigu.chapter10.array
import scala.collection.mutable.ArrayBuffer
object ArrayBuffer2JavaList {
def main(args: Array[String]): Unit = {
// Scala 集合和 Java 集合互相轉換
val scalaArr1 = ArrayBuffer("1", "2", "3")
// implicit def bufferAsJavaList[A](b : scala.collection.mutable.Buffer[A]) : java.util.List[A] = { /* compiled code */ }
import scala.collection.JavaConversions.bufferAsJavaList // 底層程式碼如上
// 物件 ProcessBuilder,因為這裡使用到上面的隱式函式 bufferAsJavaList
val javaArr = new ProcessBuilder(scalaArr1) // 為什麼可以這樣使用?使用了隱式轉換,將 Scala 的 ArrayBuffer 轉為 Java 的 List
// 這裡 arrList 就是 java 中的 List 了
val arrList = javaArr.command()
println(arrList) // 輸出 [1, 2, 3]
}
}
輸出結果如下:
[1, 2, 3]
10.6.2 Java 的 List 轉 Scala 陣列(mutable.Buffer)
示例程式碼如下:
package com.atguigu.chapter10.array
import scala.collection.mutable.ArrayBuffer
object ArrayBuffer2JavaList {
def main(args: Array[String]): Unit = {
// Scala 集合和 Java 集合互相轉換
val scalaArr1 = ArrayBuffer("1", "2", "3")
// implicit def bufferAsJavaList[A](b : scala.collection.mutable.Buffer[A]) : java.util.List[A] = { /* compiled code */ }
import scala.collection.JavaConversions.bufferAsJavaList // 底層程式碼如上
// 物件 ProcessBuilder,因為這裡使用到上面的隱式函式 bufferAsJavaList
val javaArr = new ProcessBuilder(scalaArr1) // 為什麼可以這樣使用?使用了隱式轉換,將 Scala 的 ArrayBuffer 轉為 Java 的 List
// 這裡 arrList 就是 java 中的 List 了
val arrList = javaArr.command()
println(arrList) // 輸出 [1, 2, 3]
// Java 的List 轉成 Scala 的 ArrayBuffer
// 1. asScalaBuffer 是一個隱式函式
// implicit def asScalaBuffer[A](l : java.util.List[A]) : scala.collection.mutable.Buffer[A] = { /* compiled code */ }
import scala.collection.JavaConversions.asScalaBuffer // 底層程式碼如上
import scala.collection.mutable
// java.util.List => Buffer
val scalaArr2: mutable.Buffer[String] = arrList
scalaArr2.append("jack")
scalaArr2.append("tom")
scalaArr2.remove(0)
println(scalaArr2) // ArrayBuffer(2, 3, jack, tom)
}
}
輸出結果如下:
[1, 2, 3]
ArrayBuffer(2, 3, jack, tom)
10.6.3 補充一個多型的知識點(使用 trait 來實現引數多型)
示例程式碼如下:
trait MyTrait01 {}
class A extends MyTrait01 {}
object B {
def test(m: MyTrait01): Unit = {
println("b ok...")
}
}
// 明確一個知識點:
// 當一個類繼承了一個 trait,那麼該類的例項,就可以傳遞給這個 trait 引用
val a01 = new A
B.test(a01)
10.7 元組 Tuple
10.7.1 元祖的基本介紹+元祖的建立
示例程式碼如下:
package com.atguigu.chapter10.tuple
object TupleDemo01 {
def main(args: Array[String]): Unit = {
// 建立
// 說明 1. tuple1 就是一個 Tuple,型別是 Tuple5
// 簡單說明: 為了高效的操作元組,編譯器根據元素的個數不同,對應不同的元組型別
// 分別:Tuple1 --- Tuple22
val tuple1 = (1, 2, 3, "hello", 4)
println(tuple1)
}
}
輸出結果如下:
(1,2,3,hello,4)
10.7.2 元組的建立-程式碼小結
10.7.3 元組資料的訪問+遍歷
Tuple 是一個整體,遍歷需要調其迭代器。
示例程式碼如下:
package com.atguigu.chapter10.tuple
object TupleDemo01 {
def main(args: Array[String]): Unit = {
// 建立
// 說明 1. tuple1 就是一個 Tuple,型別是 Tuple5
// 簡單說明: 為了高效的操作元組,編譯器根據元素的個數不同,對應不同的元組型別
// 分別:Tuple1 --- Tuple22
val tuple1 = (1, 2, 3, "hello", 4)
println(tuple1)
println("====================訪問元組====================")
// 訪問元組
val t1 = (1, "a", "b", true, 2)
println(t1._1) // 1 訪問元組的第一個元素,從1開始
println(t1.productElement(0)) // 0 訪問元組的第一個元素,從0開始
/* productElement 方法底層原始碼:只是使用到了模式匹配,本質是一樣
override def productElement(n: Int) = n match {
case 0 => _1
case 1 => _2
case 2 => _3
case 3 => _4
case 4 => _5
case _ => throw new IndexOutOfBoundsException(n.toString())
}
*/
println("====================遍歷元組====================")
// 遍歷元組,元組的遍歷需要使用到迭代器
for (item <- t1.productIterator) {
println("item=" + item)
}
}
}
輸出結果如下:
(1,2,3,hello,4)
====================訪問元組====================
1
1
====================遍歷元組====================
item=1
item=a
item=b
item=true
item=2
10.8 列表 List
10.8.1 建立 List + List 元素的訪問
示例程式碼如下:
package com.atguigu.chapter10.list
object ListDemo01 {
def main(args: Array[String]): Unit = {
// 說明
// 1. 在預設情況下 List 是 scala.collection.immutable.List 即不可變
// 2. 在 scala 中,List 就是不可變的,如需要使用可變的 List,則需要使用 ListBuffer
// 3. List 在 package object scala 中做了宣告 val List = scala.collection.immutable.List
// 4. val Nil = scala.collection.immutable.Nil // List()
val list01 = List(1, 2, 3, "Hello") // 建立時,直接分配元素
println(list01) // List(1, 2, 3, Hello)
val list02 = Nil // 空集合
println(list02) // List()
// 訪問 List 的元素
val value1 = list01(1) // 1是索引,表示取出第2個元素
println("value1=" + value1) // 2
}
}
輸出結果如下:
List(1, 2, 3, Hello)
List()
value1=2
10.8.2 建立 List 的應用案例小結
10.8.3 List 元素的追加
方式1-在列表的最後增加資料
方式2-在列表的最前面增加資料
方式3-在列表的最後增加資料
示例程式碼如下:
package com.atguigu.chapter10.list
object ListDemo01 {
def main(args: Array[String]): Unit = {
// 說明
// 1. 在預設情況下 List 是 scala.collection.immutable.List 即不可變
// 2. 在 scala 中,List 就是不可變的,如需要使用可變的 List,則需要使用 ListBuffer
// 3. List 在 package object scala 中做了宣告 val List = scala.collection.immutable.List
// 4. val Nil = scala.collection.immutable.Nil // List()
val list01 = List(1, 2, 3, "Hello") // 建立時,直接分配元素
println(list01) // List(1, 2, 3, Hello)
val list02 = Nil // 空集合
println(list02) // List()
// 訪問 List 的元素
val value1 = list01(1) // 1是索引,表示取出第2個元素
println("value1=" + value1) // 2
println("====================list追加元素後的效果====================")
// 通過 :+ 和 +: 給 list 追加元素(本身的集合並沒有變化
// )
val list1 = List(1, 2, 3, "abc")
// :+運算子表示在列表的最後增加資料
val list2 = list1 :+ 4 // (1,2,3,"abc", 4)
println(list1) // list1 沒有變化 (1, 2, 3, "abc"),說明 list1 還是不可變
println(list2) // 新的列表結果是 [1, 2, 3, "abc", 4]
val list3 = 10 +: list1 // (10, 1, 2, 3, "abc")
println("list3=" + list3)
// :: 符號的使用
val list4 = List(1, 2, 3, "abc")
// 說明 val list5 = 4 :: 5 :: 6 :: list4 :: Nil 步驟
// 1. List()
// 2. List(List(1, 2, 3, "abc"))
// 3. List(6, List(1, 2, 3, "abc"))
// 4. List(5, 6, List(1, 2, 3, "abc"))
// 5. List(4, 5, 6, List(1, 2, 3, "abc"))
val list5 = 4 :: 5 :: 6 :: list4 :: Nil
println("list5=" + list5)
// ::: 符號的使用
// 說明 val list6 = 4 :: 5 :: 6 :: list4 ::: Nil 步驟
// 1. List()
// 2. List(1, 2, 3, "abc")
// 3. List(6, 1, 2, 3, "abc")
// 4. List(5, 6, 1, 2, 3, "abc")
// 5. List(4, 5, 6, 1, 2, 3, "abc")
// 下面等價 4 :: 5 :: 6 :: list1
val list6 = 4 :: 5 :: 6 :: list4 ::: Nil
println("list6=" + list6)
}
}
輸出結果如下:
List(1, 2, 3, Hello)
List()
value1=2
====================list追加元素後的效果====================
List(1, 2, 3, abc)
List(1, 2, 3, abc, 4)
list3=List(10, 1, 2, 3, abc)
list5=List(4, 5, 6, List(1, 2, 3, abc))
list6=List(4, 5, 6, 1, 2, 3, abc)
List元素的追加練習題
10.8.4 ListBuffer
ListBuffer 是可變的 list 集合,可以新增、刪除元素,ListBuffer 屬於序列。
// 檢視一下繼承關係即可
Seq var listBuffer = ListBuffer(1, 2)
示例程式碼如下:
package com.atguigu.chapter10.list
import scala.collection.mutable.ListBuffer
object ListBufferDemo01 {
def main(args: Array[String]): Unit = {
// 建立 ListBuffer
val list0 = ListBuffer[Int](1, 2, 3)
println(list0) // ListBuffer(1, 2, 3)
// 訪問 ListBuffer 中的元素
println("list0(2)=" + list0(2))
// 遍歷
for (item <- list0) {
println("item=" + item)
}
// 動態的增加元素,lst1 就會變化,增加一個一個的元素
val list1 = new ListBuffer[Int] // 空的ListBuffer
list1 += 4
list1.append(5)
println(list1) // ListBuffer(4, 5)
list1.append(5, 6)
println(list1) // ListBuffer(4, 5, 5, 6)
list0 ++= list1
println(list0) // ListBuffer(1, 2, 3, 4, 5, 5, 6)
val list2 = list0 ++ list1
println(list2) // ListBuffer(1, 2, 3, 4, 5, 5, 6, 4, 5, 5, 6)
val list3 = list0 :+ 5
println(list3) // ListBuffer(1, 2, 3, 4, 5, 5, 6, 5)
println("==========刪除==========")
println("list1=" + list1) // lst1=ListBuffer(4, 5, 5, 6)
list1.remove(1) // 表示將索引為1的元素刪除(索引從0開始)
for (item <- list1) {
println("item=" + item)
}
}
}
輸出結果如下:
ListBuffer(1, 2, 3)
list0(2)=3
item=1
item=2
item=3
ListBuffer(4, 5)
ListBuffer(4, 5, 5, 6)
ListBuffer(1, 2, 3, 4, 5, 5, 6)
ListBuffer(1, 2, 3, 4, 5, 5, 6, 4, 5, 5, 6)
ListBuffer(1, 2, 3, 4, 5, 5, 6, 5)
==========刪除==========
list1=ListBuffer(4, 5, 5, 6)
item=4
item=5
item=6
10.9 佇列 Queue
佇列的應用場景:銀行排隊的案例。
佇列的說明
補充:操作符的過載 演示
示例程式碼如下:
package com.atguigu.chapter10.queue
/**
* 操作符的過載
*/
object OperatorOverloadDemo {
def main(args: Array[String]): Unit = {
val cat = new Cat
cat + 10
cat + 20
println("cat.age=" + cat.age)
cat.+(9)
println("cat.age=" + cat.age)
}
}
class Cat {
var age = 0
def +(n: Int): Unit = {
this.age += n
}
}
輸出結果如下:
cat.age=30
cat.age=39
10.9.1 佇列的建立+追加資料
10.9.2 刪除和加入佇列元素+返回佇列元素
10.9.1~10.9.2示例程式碼如下:
package com.atguigu.chapter10.queue
import scala.collection.mutable
object QueueDemo01 {
def main(args: Array[String]): Unit = {
// 說明: 這裡的 Int 是泛型,表示 q1 佇列只能存放 Int 型別。
// 如果希望 q1 可以存放其它型別,則使用 Any 即可。
val q1 = new mutable.Queue[Int]
println(q1) // Queue()
// 給佇列增加元素
q1 += 9
println("q1=" + q1) // q1=Queue(9)
q1 ++= List(4,5,7) // 預設值直接加在佇列後面
println("q1=" + q1) // q1=Queue(9, 4, 5, 7)
// q1 += List(10, 0) // 佇列的泛型為 Any 才ok,表示將 List(10, 0) 作為一個元素加入到佇列中
println("==========刪除和加入佇列元素==========")
// dequeue 從佇列的頭部取出元素,q1 本身會變
val queueElement = q1.dequeue()
println("queueElement=" + queueElement + " q1=" + q1) // queueElement=9 q1=Queue(4, 5, 7)
// enQueue 入佇列,預設是從佇列的尾部加入,Redis
q1.enqueue(100, 10, 100, 888)
println("q1=" + q1) // q1=Queue(4, 5, 7, 100, 10, 100, 888)
println("==========返回佇列的元素==========")
// 1. 獲取佇列的第一個元素
println(q1.head) // 4 對q1沒有任何影響
// 2. 獲取佇列的最後一個元素
println(q1.last) // 888 對q1沒有任何影響
// 3. 取出隊尾的資料,即:返回除了第一個以外剩餘的元素,可以級聯使用,這個在遞迴時使用較多。
println(q1.tail) // Queue(5, 7, 100, 10, 100, 888)
println(q1.tail.tail.tail.tail) // Queue(10, 100, 888)
}
}
輸出結果如下:
Queue()
q1=Queue(9)
q1=Queue(9, 4, 5, 7)
==========刪除和加入佇列元素==========
queueElement=9 q1=Queue(4, 5, 7)
q1=Queue(4, 5, 7, 100, 10, 100, 888)
==========返回佇列的元素==========
4
888
Queue(5, 7, 100, 10, 100, 888)
Queue(10, 100, 888)
10.10 對映 Map
10.10.1 Map 的基本介紹
Java 中的 Map 回顧
HashMap 是一個雜湊表(陣列+連結串列),它儲存的內容是鍵值對(key-value)對映,Java 中的 HashMap 是無序的,key 不能重複
。
示例程式碼如下:
package com.atguigu.chapter10.map;
import java.util.HashMap;
public class JavaMapTest {
public static void main(String[] args) {
// Java中的HashMap是無序的,key不能重複。
HashMap<String, Integer> hm = new HashMap();
hm.put("no1", 100);
hm.put("no2", 200);
hm.put("no3", 300);
hm.put("no4", 400);
System.out.println(hm); // {no2=200, no1=100, no4=400, no3=300}
System.out.println(hm.get("no2")); // 20
}
}
輸出結果如下:
{no2=200, no1=100, no4=400, no3=300}
200
Scala 中的 Map 介紹
Scala 中的 Map 和 Java 類似,也是一個雜湊表,它儲存的內容也是鍵值對(key-value)對映,Scala 中不可變的 Map 是有序的,可變的 Map 是無序的
。
Scala 中,有可變 Map (scala.collection.mutable.Map) 和 不可變 Map(scala.collection.immutable.Map)。
10.10.2 Map 的建立
方式1-構造不可變對映
Scala 中的不可變 Map 是有序,構建 Map 中的元素底層是 Tuple2 型別。
方式2-構造可變對映
需要指定可變 Map 的包。
方式3-建立空的對映
val map3 = new scala.collection.mutable.HashMap[String, Int]
方式4-對偶元組
即建立包含鍵值對的二元組,和第一種方式等價,只是形式上不同而已。
對偶元組:就是隻含有兩個資料的元組。
10.10.3 Map 的取值
方式1-使用 map(key)
1、如果 key 存在,則返回對應的值。
2、如果 key 不存在,則丟擲異常 [java.util.NoSuchElementException]。
3、在 Java 中,如果 key 不存在則返回 null。
方式2-使用 contains 方法檢查是否存在 key
使用 containts 先判斷再取值,可以防止異常,並加入相應的處理邏輯。
1、如果key存在,則返回 true。
2、如果key不存在,則返回 false。
方式3-使用 map.get(key).get 取值
1、如果 key 存在 map.get(key) 就會返回 Some(值),然後 Some(值).get 就可以取出。
2、如果 key 不存在 map.get(key) 就會返回 None。
方式4-使用 map4.getOrElse() 取值
底層是:def getOrElse[V1 >: V](key: K, default: => V1)
1、如果key存在,返回key對應的值。
2、如果key不存在,返回預設值。在java中底層有很多類似的操作。
如何選擇取值方式建議
如果我們確定 map 有這個 key,則應當使用 map(key),速度快。
如果我們不能確定 map 是否有 key,而且有不同的業務邏輯,使用 map.contains() 先判斷再加入邏輯。
如果只是簡單的希望得到一個值,使用 map4.getOrElse("ip", "127.0.0.1")
10.10.4 可變 Map 的修改、新增和刪除
說明:
map 是可變的,才能修改,否則報錯。
如果 key 存在:則修改對應的值,key 不存在,等價於新增一個 key-val。
說明:
"A","B" 就是要刪除的 key, 可以寫多個。
如果 key 存在,就刪除,如果 key 不存在,也不會報錯。
10.10.5 Map 的遍歷
10.10.2~10.10.5的所有示例程式碼如下:
package com.atguigu.chapter10.map
import scala.collection.mutable
object ScalaMapDemo01 {
def main(args: Array[String]): Unit = {
println("====================1、Map 的建立====================")
// 方式1-構造不可變對映
// 1.預設 Map 是 immutable.Map
// 2.key-value 型別支援 Any
// 3.在 Map 的底層,每對 key-value 是元組 Tuple2
// 4.從輸出的結果看到,輸出順序和宣告順序一致
val map1 = Map("Alice" -> 10, "Bob" -> 20, "Kotlin" -> "北京")
println(map1) // Map(Alice -> 10, Bob -> 20, Kotlin -> 北京)
// 方式2-構造可變對映(需要指定可變Map的包)
// 1.從輸出的結果看到,可變的 map 輸出順序和宣告順序不一致
val map2 = mutable.Map("Alice" -> 10, "Bob" -> 20, "Kotlin" -> "北京")
println(map2) // Map(Bob -> 20, Kotlin -> 北京, Alice -> 10)
// 方式3-建立空的對映
val map3 = new scala.collection.mutable.HashMap[String, Int]
println("map3=" + map3) // map3=Map()
// 方式4-對偶元組(即建立包含鍵值對的二元組, 和第一種方式等價,只是形式上不同而已)
val map4 = mutable.Map(("Alice", 10), ("Bob", 20), ("Kotlin", "北京"))
println("map4=" + map4) // map4=Map(Bob -> 20, Kotlin -> 北京, Alice -> 10)
println("====================2、Map 的取值====================")
// 方式1-使用 map(key)
println(map4("Alice")) // 10
// 丟擲異常(java.util.NoSuchElementException: key not found:)
// println(map4("Alice~~~"))
// 方式2-使用 contains 方法檢查是否存在 key。
if (map4.contains("Alice")) {
println("key存在,值=" + map4("Alice"))
} else {
println("key不存在:)")
}
// 方式3-使用 map.get(key).get 取值
// 1. 如果 key 存在 map.get(key) 就會返回 Some(值),然後 Some(值).get 就可以取出。
// 2. 如果 key 不存在 map.get(key) 就會返回 None。
println(map4.get("Alice").get)
// println(map4.get("Alice~~~").get) // 丟擲異常 java.util.NoSuchElementException: None.get
// 方式4-使用 map4.getOrElse() 取值 底層是:def getOrElse[V1 >: V](key: K, default: => V1)
// 1. 如果key存在,返回key對應的值。
// 2. 如果key不存在,返回預設值。在java中底層有很多類似的操作。
println(map4.getOrElse("Alice~~~", "預設的值")) // 第一個引數是 key,第二個引數是 預設的值
println("====================3、Map 的修改、新增和刪除====================")
val map5 = mutable.Map(("A", 1), ("B", "北京"), ("C", 3))
println("map5=" + map5) // map5=Map(A -> 1, C -> 3, B -> 北京)
map5("A") = 20 // 修改
println("map5=" + map5) // map5=Map(A -> 20, C -> 3, B -> 北京)
map5 += ("A" -> 100) // 如果 key 存在:則修改對應的值;如果 key 不存在,等價於新增一個 key-val
// val map6 = map5 + ("E"->1, "F"->3) // 增加多個元素
println("map5=" + map5) // map5=Map(A -> 100, C -> 3, B -> 北京)
map5 -= ("A", "B", "AAA") // 刪除多個元素,如果 key 存在,就刪除,如果 key 不存在,也不會報錯
// val map6 = map5 - ("A", "B") // 刪除多個元素
println("map5=" + map5) // map5=Map(C -> 3)
println("====================4、Map 的遍歷====================")
val map6 = mutable.Map(("A", 1), ("B", "北京"), ("C", 3))
println("----------(k, v) <- map6----------")
for ((k, v) <- map6) println(k + " is mapped to " + v)
println("----------v <- map6.keys----------")
for (v <- map6.keys) println(v)
println("----------v <- map6.values----------")
for (v <- map6.values) println(v)
println("----------v <- map6----------")
for (v <- map6) println(v + " key =" + v._1 + " val=" + v._2) // v 型別是 Tuple2
}
}
輸出結果如下:
====================1、Map 的建立====================
Map(Alice -> 10, Bob -> 20, Kotlin -> 北京)
Map(Bob -> 20, Kotlin -> 北京, Alice -> 10)
map3=Map()
map4=Map(Bob -> 20, Kotlin -> 北京, Alice -> 10)
====================2、Map 的取值====================
10
key存在,值=10
10
預設的值
====================3、Map 的修改、新增和刪除====================
map5=Map(A -> 1, C -> 3, B -> 北京)
map5=Map(A -> 20, C -> 3, B -> 北京)
map5=Map(A -> 100, C -> 3, B -> 北京)
map5=Map(C -> 3)
====================4、Map 的遍歷====================
----------(k, v) <- map6----------
A is mapped to 1
C is mapped to 3
B is mapped to 北京
----------v <- map6.keys----------
A
C
B
----------v <- map6.values----------
1
3
北京
----------v <- map6----------
(A,1) key =A val=1
(C,3) key =C val=3
(B,北京) key =B val=北京
10.11 集 Set
10.11.1 Set 基本介紹
Java 中 Set 的回顧
java 中,HashSet 是實現 Set<E>
介面的一個實體類,資料是以雜湊表的形式存放的,裡面的不能包含重複資料。Set 介面是一種不包含重複元素的 collection,HashSet 中的資料也是沒有順序的。
示例程式碼如下:
package com.atguigu.chapter10.set;
import java.util.HashSet;
public class JavaSetTest {
public static void main(String[] args) {
HashSet hs = new HashSet<String>();
hs.add("jack");
hs.add("tom");
hs.add("jack");
hs.add("jack2");
System.out.println(hs); // [jack2, tom, jack]
}
}
輸出結果如下:
[jack2, tom, jack]
Scala 中的 Set 介紹
集是不重複元素的結合
。集不保留順序,預設是以雜湊集實現。
預設情況下,Scala 使用的是不可變集合,如果你想使用可變集合,需要引用 scala.collection.mutable.Set 包。
10.11.2 Set 的建立
Set 不可變集合的建立
Set 可變集合的建立
10.11.3 Set 的取值
10.11.4 可變 Set 的修改、新增和刪除
說明:
如果新增的物件已經存在,則不會重複新增,也不會報錯。
Scala 的 Set 可以直接刪除值。
如果刪除的物件不存在,則不生效,也不會報錯。
10.11.5 Set 的遍歷
10.11.2~10.11.5的所有示例程式碼如下:
示例程式碼如下:
package com.atguigu.chapter10.set
import scala.collection.mutable
object ScalaSetDemo01 {
def main(args: Array[String]): Unit = {
println("====================1、Set 的建立====================")
val set1 = Set(1, 2, 3) // 不可變
println(set1)
println(set1.max)
println(set1.min)
val set2 = mutable.Set(1, 2, "hello") // 可以變
println(set2)
println("====================2、Set 的取值====================")
println("====================3、可變 Set 的修改、新增和刪除====================")
val set3 = mutable.Set(1, 2, 4, "abc")
// 新增
set3.add(90) // 新增元素方式1,如果新增的物件已經存在,則不會重複新增,也不會報錯。
set3 += 78 // 新增元素方式2
set3.+= (90) // 新增元素方式3
println(set3) // Set(78, 1, 2, abc, 90, 4)
// 刪除
set3 -= 2 // 操作符形式,如果刪除的物件不存在,則不生效,也不會報錯。
set3.remove("abc") // 方法的形式,Scala 的 Set 可以直接刪除值。
println(set3) // Set(78, 1, 90, 4)
println("====================4、Set 的遍歷====================")
for(x <- set3) {
println(x)
}
}
}
輸出結果如下:
====================1、Set 的建立====================
Set(1, 2, 3)
3
1
Set(1, 2, hello)
====================2、Set 的取值====================
====================3、可變 Set 的修改、新增和刪除====================
Set(78, 1, 2, abc, 90, 4)
Set(78, 1, 90, 4)
====================4、Set 的遍歷====================
78
1
90
4
10.12 Set 的更多操作
檢視集 Set 的更多使用方法,可以檢視相關的文件。
Scala 官方API-2.11.8:https://www.scala-lang.org/api/2.11.8/#package
Set 常用方法列表