zoukankan      html  css  js  c++  java
  • Scala集合基础

    [toc]

    ## Scala集合基础

    > 1. Scala同时支持不可变集合和可变集合,不可变集合可以安全的并发访问。Scala默认采用不可变集合,对于几乎所有的集合类,Scala都同时提供了可变(mutable)和不可变(immutable)的版本。
    > 2. 两个主要的包:
    > 1. 不可变集合:`scala.collection.immutable`
    > 2. 可变集合: `scala.collection.mutable`
    > 3. Scala的集合有三大类:`序列Seq、集Set、映射Map`,所有的集合都扩展自`Iterable特质`,在Scala中集合有可变(mutable)和不可变(immutable)两种类型。
    > 4. 可变集合和不可变集合举例:
    > 1. 不可变集合:Scala不可变集合,就是这个集合本身不能动态变化。(类似java的数组,是不可以动态增长的)
    > 2. 可变集合:可变集合,就是这个集合本身可以动态变化的。(比如:ArrayList , 是可以动态增长的)

    ```java
    package com.atguigu.chapter10;

    import java.util.ArrayList;

    /**
    * @Date 2021/4/1 15:07
    * @Version 10.21
    * @Author DuanChaojie
    */
    public class JavaCollection {
    public static void main(String[] args) {
    // 不可变集合类似java的数组
    int[] nums = new int[3];
    nums[2] = 11;
    nums[2] = 22;
    //nums[3] = 90; //报错

    String[] names = {"bj", "sh"};
    System.out.println(nums + " " + names);

    //可变集合举例
    ArrayList al = new ArrayList<String>();
    al.add("zs");
    al.add("zs2");

    System.out.println(al + " 地址= " + al.hashCode()); //地址
    al.add("zs3");
    System.out.println(al + " 地址2=" + al.hashCode()); //地址
    }
    }
    ```

    ### 1. Scala不可变集合继承关系一览图

    ![image-20210401215736216](assets/image-20210401215736216.png)

    > 对上图的总结:
    >
    > 1. Set、Map是Java中也有的集合
    > 2. Seq是Java没有的,我们发现List归属到Seq了,因此这里的List就和java不是同一个概念了
    > 3. 我们前面的for循环有一个 1 to 3 ,就是IndexedSeq 下的Vector
    > 4. String也是属于IndexedSeq
    > 5. 我们发现经典的数据结构比如Queue 和 Stack被归属到LinearSeq
    > 6. 大家注意Scala中的Map体系有一个SortedMap,说明Scala的Map可以支持排序
    > 7. IndexSeq 和 LinearSeq 的区别
    > 1. IndexSeq是通过索引来查找和定位,因此速度快,比如String就是一个索引集合,通过索引即可定位
    > 2. LineaSeq 是线型的,即有头尾的概念,这种数据结构一般是通过遍历来查找,它的价值在于应用到一些具体的应用场景 (电商网站, 大数据推荐系统 ——最近浏览的10个商品)

    ### 2. Scala可变集合继承关系一览图☆

    ![image-20210401220109739](assets/image-20210401220109739.png)

    > 对上图的小结:
    >
    > 1. 在可变集合中比不可变集合更加丰富
    > 2. 在Seq集合中,增加了Buffer 集合,将来开发中,我们常用的有ArrayBuffer和 ListBuffer
    > 3. 如果涉及到线程安全可以选择使用syn..开头的集合
    > 4. 其它的说明参考不可变集合

    ### 3. Scala数组Array和ArrayBuffer

    #### 定长数组Array

    > 1. 第一种方式定义数组
    > 2. 这里的数组等同于Java中的数组,中括号的类型就是数组的类型
    > 3. `val arr1 = new Array[Int](10)`
    > 4. 赋值——集合元素采用小括号访问 `arr1(1) = 7`

    ~~~~scala
    /**
    * @Date 2021/4/1 15:13
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ArrayDemo01 {
    def main(args: Array[String]): Unit = {
    /**
    * 说明
    * 1. 创建了一个Array对象,
    * 2. [Int] 表示泛型,即该数组中,只能存放Int
    * 3. [Any] 表示 该数组可以存放任意类型
    * 4. 在没有赋值情况下,各个元素的值 0
    * 5. arr(3) = 10 表示修改 第4个元素的值
    */
    val arr = new Array[Int](4) //底层 int[] arr = new int[4]
    println(arr.length) // 4

    println("arr01(0)=" + arr(0)) // 0
    //数据的遍历

    for (i <- arr) {
    println(i)
    }

    println("--------------------")

    arr(3) = 10 //修改
    for (i <- arr) {
    println(i)
    }
    }
    }
    ~~~~

    > 1. 第二种方式定义数组
    > 2. 在定义数组时,直接赋值
    > 3. 使用apply方法创建数组对象 `val arr1 = Array(1, 2)`

    ~~~~scala
    /**
    * @Date 2021/4/1 15:18
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ArrayDemo02 {
    def main(args: Array[String]): Unit = {
    /**
    * 说明
    * 1. 使用的是 object Array 的apply方法
    * 2. 直接初始化数组,这时因为你给了 整数和 "", 这个数组的泛型就Any
    * 3. 遍历方式一样
    */
    var arr = Array(1, 3, "xx")
    arr(1) = "xx"

    // 遍历
    for (i <- arr) {
    println(i)
    }

    // 可以使用我们传统的方式遍历,使用下标的方式遍历
    for (index <- 0 until arr.length) {
    printf("arr(%d) = %s", index, arr(index) + "\t")
    }
    }
    }
    ~~~~

    #### 变长数据ArrayBuffer

    > 基本使用和应用案例
    >
    > 1. 声明`val arr2 = ArrayBuffer`
    > 2. 追元素 `arr2.append(7)`
    > 3. 重新赋值 `arr2(0) = 7`
    >
    > ==学习集合的流程(创建-->查询-->修改-->删除)==

    ```scala
    /**
    * @Date 2021/4/1 15:59
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ArrayBufferDemo01 {
    def main(args: Array[String]): Unit = {
    // 创建ArrayBuffer
    val arrBuf = ArrayBuffer[Any](3, 2, 5)

    // 通过下标访问数据
    println("arrBuf(1) = " + arrBuf(1))
    // 遍历arrBuf
    for(item <- arrBuf){
    println(item)
    }

    // arrBuf的长度
    println(arrBuf.length)
    println(arrBuf.hashCode())

    // 使用append方法追加数据,append支持可变参数
    arrBuf.append(11,12,13)

    println("------------------------------------")
    arrBuf(4) = 999
    // 再次遍历arrBuf
    for(item <- arrBuf){
    println(item)
    }

    // 根据下标删除数据
    arrBuf.remove(5)

    println("------------------------------------")

    // 再次遍历arrBuf
    for(item <- arrBuf){
    println(item)
    }
    }
    }
    ```

    > 变长数组分析小结:
    >
    > 1. ArrayBuffer是变长数组,类似java的ArrayList
    > 2. `val arr2 = ArrayBuffer[Int]()` 也是使用的apply方法构建对象
    > 3. `def append(elems: A*) { appendAll(elems) }` 接收的是可变参数
    > 4. 每append一次,arr在底层会重新分配空间,进行扩容,arr2的内存地址会发生变化,也就成为新的ArrayBuffer

    #### Array与ArrayBuffer的转换

    > 在开发中,我们可能使用对定长数组和变长数组,进行转换:
    >
    > 1. `arr1.toBuffer`:定长数组转可变数组, arr1本身没有变化
    > 2. `arr2.toArray` :定长数组转可变数组, arr2本身没有变化

    ~~~scala
    package com.atguigu.chapter10.array

    import scala.collection.mutable.ArrayBuffer

    /**
    * @Date 2021/4/1 18:13
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ArrayToToArrayBuffer {
    def main(args: Array[String]): Unit = {
    val arrBuf = new ArrayBuffer[Int]()
    arrBuf.append(1, 2, 3, 4)
    // ArrayBuffer(1, 2, 3, 4)
    println(arrBuf)

    /** ArrayBuffer转Array
    * 1. arrBuf.toArray 调用 arrBuf 的方法 toArray
    * 2. 将 ArrayBuffer ---> Array
    * 3. arrBuf本身没有任何变化
    */
    val arr = arrBuf.toArray
    for (item <- arr) {
    println(item)
    }
    println("arr.length = " + arr.length)

    println("--------------------------------------------------")
    val array = new Array[Int](4)
    for (index <- 0 until array.length) {
    array(index) = index
    }

    for (item <- array) {
    println(item)
    }

    println("-------------------------------------------------")
    /**
    Array 转 ArrayBuffer 底层的实现
    override def toBuffer[A1 >: A]: mutable.Buffer[A1] = {
    val result = new mutable.ArrayBuffer[A1](size)
    copyToBuffer(result)
    result
    }
    */
    val buffer = array.toBuffer
    buffer.append(5, 6, 7, 8)
    for (item <- buffer) {
    println(item)
    }

    }
    }
    ~~~

    #### 多维数组的定义和使用

    > 1. 定义 `val arr = Array.ofDim[T](3,4)`
    > 2. 说明:二维数组中有三个一维数组,每个一维数组中有四个元素
    > 3. 赋值: `arr(1)(1) = 11.11`

    ```scala
    package com.atguigu.chapter10.array

    /**
    * @Date 2021/4/1 18:22
    * @Version 10.21
    * @Author DuanChaojie
    */
    object MultiplyArray {
    def main(args: Array[String]): Unit = {
    //声明一个二维数组,三行四列
    val arr = Array.ofDim[Int](3, 4)

    // 修改值
    for (i <- 0 until arr.length) {
    for (j <- 0 until arr(i).length) {
    arr(i)(j) = i * j
    }
    }

    // 遍历二维数据arr
    for (i1 <- arr) { //取出二维数组的各个元素(一维数组)
    for (i2 <- i1) {
    print(i2)
    }
    println()
    }

    println("-------------------------------------")
    println(arr(2)(3))

    }
    }
    ```

    #### Scala数组与Java的List互相转换

    ~~~~scala
    /**
    * @Date 2021/4/1 18:36
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ArrayBufferToJavaList {
    def main(args: Array[String]): Unit = {
    // Scala集合 和 Java集合互相转换
    val arr = ArrayBuffer("1", "2", "3")
    /**
    implicit def bufferAsJavaList[A](b : scala.collection.mutable.Buffer[A]) : java.util.List[A] = { /* compiled code */ }
    */
    // ProcessBuilder对象,因为这里使用到上面的bufferAsJavaList
    import scala.collection.JavaConversions.bufferAsJavaList
    val javaArr = new ProcessBuilder(arr)
    // 这里arrList 就是java中的List
    val arrList = javaArr.command()

    println(arrList)

    /** asScalaBuffer 是一个隐式函数
    implicit def asScalaBuffer[A](l : java.util.List[A]) : scala.collection.mutable.Buffer[A] = { /* compiled code */ }
    */

    import scala.collection.JavaConversions.asScalaBuffer
    // java.util.List ==> Buffer
    val scalaArr:mutable.Buffer[String] = arrList
    scalaArr.append("jack")
    scalaArr.append("tom")
    scalaArr.remove(0)

    println(scalaArr)

    // 删除
    scalaArr.remove(0)
    println(scalaArr)
    }
    }
    ~~~~

    ### 4. Scala元组Tuple

    > 1. 元组也是可以理解为一个容器,可以存放各种相同或不同类型的数据。说的简单点,就是将多个无关的数据封装为一个整体,称为元组, 最多的特点灵活,对数据没有过多的约束。
    >
    > 2. `注意:元组中最大只能有22个元素`
    >
    > 3. 元组的创建:
    >
    > 1. `val tuple = (1, 2, 3, "hello", 4)`
    >
    > 2. ~~~scala
    > // Tuple3
    > final case class Tuple3[+T1, +T2, +T3](_1: T1, _2: T2, _3: T3)
    > extends Product3[T1, T2, T3] {
    > override def toString() = "(" + _1 + "," + _2 + "," + _3 + ")"
    > }
    > ~~~
    >
    > 4. 访问元组中的数据:
    >
    > 1. 可以采用顺序号(`_顺序号`)
    > 2. 也可以通过索引(`productElement`)访问。
    >
    > 5. Tuple是一个整体,遍历需要调其迭代器`tuple.productIterator`。

    ```scala
    package com.atguigu.chapter10.tuple

    /**
    * @Date 2021/4/1 19:29
    * @Version 10.21
    * @Author DuanChaojie
    */
    object TupleDemo01 {
    def main(args: Array[String]): Unit = {

    /**
    * 说明
    * 1. tuple 就是一个Tuple类型是Tuple5
    * 2. 简单说明: 为了高效的操作元组 , 编译器根据元素的个数不同,对应不同的元组类型
    * 3. 分别 Tuple1----Tuple22
    * 4. 元组是只读的不可修改
    */
    val tuple = (1, 2, 3, "hello", 4)


    // 访问元组
    println(tuple)
    // 访问元组的第一个元素,从1开始
    println(tuple._1)
    println(tuple._4)

    /** 访问元组的第一个元素,从0开始
    *
    * @throws(classOf[IndexOutOfBoundsException])
    * 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(tuple.productElement(4))

    println("==================遍历元组=========================")
    //遍历元组, 元组的遍历需要使用到迭代器
    for (item <- tuple.productIterator) {
    println(item)
    }

    }
    }
    /*
    final case class Tuple3[+T1, +T2, +T3](_1: T1, _2: T2, _3: T3)
    extends Product3[T1, T2, T3] {
    override def toString() = "(" + _1 + "," + _2 + "," + _3 + ")"
    }*/
    ```

    ### 5. Scala列表List和ListBuffer

    #### List

    > 1. Scala中的List 和Java List 不一样,在Java中List是一个接口,真正存放数据是ArrayList,而Scala的List可以直接存放数据,就是一个object,`默认情况下Scala的List是不可变的,List属于序列Seq。`
    > 2. `val List = scala.collection.immutable.List`
    > 3. `object List extends SeqFactory[List]`
    > 4. 创建List应用小结:
    > 1. List默认为不可变的集合
    > 2. List 在 scala包对象声明的,因此不需要引入其它包也可以使用`val List = scala.collection.immutable.List`
    > 3. List 中可以放任何数据类型,`比如 arr1的类型为 List[Any]`
    > 4. 如果希望得到一个空列表,可以使用`Nil对象`, 在 Scala包对象声明的,因此不需要引入其它包也可以使用`val Nil = scala.collection.immutable.Nil`
    > 5. List的元素追加:
    > 1. 向列表中增加元素, 会返回新的列表/集合对象。注意:Scala中List元素的追加形式非常独特,和Java不一样。
    > 2. `:+` 元素
    > 3. `+:` 集合
    > 4. `::` 表示向集合中添加元素(最后生成新集合)。
    > 5. `:::`运算符是将集合中的每一个元素加入到空集合中去
    > 6. `::`和`:::`注意事项
    > 1. 运算时,集合对象一定要放置在最右边。
    > 2. 运算规则,从右向左。

    ```scala
    /**
    * @Date 2021/4/1 19:41
    * @Version 10.21
    * @Author DuanChaojie
    */
    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 list = List(1, 2, 4)
    // List(1, 2, 4)
    println(list)

    // 空集合
    val nil = Nil
    //List()
    println(nil)

    // 取出list的第二个元素
    println(list(1))

    // 目前list(1,3,4)
    println("----------------list追加元素后的效果-------------------------")
    /**
    * 通过 :+ 和 +: 给list追加元素,生成新的集合,源集合没有变化
    */
    val list1 = list :+ 5

    // List(1, 2, 4, 5)
    println(list1)
    val list2 = 0 +: list1
    // List(0, 1, 2, 4, 5)
    println(list2)

    println("----------------:: 符号的使用-------------------------")
    /**
    * :: 符号的使用
    */
    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")
    val list6 = 4 :: 5 :: 6 :: list4 ::: Nil
    println("list6=" + list6)
    println("注意::和:::的区别!")
    }
    }
    ```

    ![image-20210401224252622](assets/image-20210401224252622.png)

    #### ListBuffer

    > ListBuffer是可变的list集合,可以添加,删除元素,ListBuffer属于序列。`Seq var listBuffer = ListBuffer(1,2)`

    ~~~~scala
    package com.atguigu.chapter10.list

    import scala.collection.mutable.ListBuffer

    /**
    * @Date 2021/4/1 20:01
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ListBufferDemo01 {
    def main(args: Array[String]): Unit = {

    // 创建ListBuffer
    val listBuf1 = ListBuffer[Int](1, 2, 3)
    // 遍历listBuf,有序
    for (item <- listBuf1) {
    println(item)
    }
    println(listBuf1(2))
    println("listBuf1 = " + listBuf1)

    println("--------------ListBuffer添加元素----------------")
    // 动态的增加元素,listBuf1就会变化
    val listBuf2 = new ListBuffer[Int] // 空的ListBuffer
    listBuf2 += 4
    println("listBuf2 = " + listBuf2)
    listBuf2.append(5)
    println("listBuf2 = " + listBuf2)

    // ListBuffer(1, 2, 3) listBuf1
    // +
    // ListBuffer(4, 5) listBuf2
    // ||
    // ListBuffer(4, 5, 1, 2, 3)
    listBuf2 ++= listBuf1
    println("listBuf2 = " + listBuf2)

    val listBuf3 = listBuf1 ++ listBuf2
    // ListBuffer(1, 2, 3, 4, 5, 1, 2, 3)
    println("listBuf3 = " + listBuf3)
    val listBuf4 = listBuf3 :+ 4
    println("listBuf4 = " + listBuf4)

    println("----------------------listBuf4.remove(4)----------------------------")
    listBuf4.remove(4)
    println("listBuf4 = " + listBuf4)


    }
    }
    ~~~~

    ### 6. Scala队列Queue

    > 队列的应用场景——银行排队的案例
    >
    > ![image-20210401224548003](assets/image-20210401224548003.png)
    >
    > 队列的说明:
    >
    > 1. 队列是一个有序列表,在底层可以用数组或是链表来实现。
    > 2. 其输入和输出要遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出
    > 3. 在Scala中,由设计者直接给我们提供队列类型使用。
    > 4. `在scala中, 有 scala.collection.mutable.Queue 和 scala.collection.immutable.Queue , 一般来说,我们在开发中通常使用可变集合中的队列。`

    ```scala
    package com.atguigu.chapter10.queue

    import scala.collection.mutable
    /**
    * @Date 2021/4/1 20:17
    * @Version 10.21
    * @Author DuanChaojie
    */
    object QueueDemo01 {
    def main(args: Array[String]): Unit = {
    // 创建队列
    val queue1 = new mutable.Queue[Any]
    // 给队列增加元素
    queue1 += 9
    println("queue1 = " + queue1)
    // 直接加在队列后面
    queue1 ++= List(8, 7)
    // queue1 = Queue(9,8,7)
    println("queue1 = " + queue1)

    //queue1 += List(6, 5) // 将List(6,5)作为一个元素加入到队列中
    //queue1 = Queue(9, 8, 7, List(6, 5))

    //queue1.enqueue(1,3,4)
    //queue1.dequeue()

    println("queue1 = " + queue1)

    queue1 ++= List(6, 5)
    println("============Queue返回队列的元素=================")
    //队列 Queue返回队列的元素

    //1. 获取队列的第一个元素
    println(queue1.head) //对queue1没有任何影响

    //2. 获取队列的最后一个元素
    println(queue1.last) // 对queue1没有任何影响

    //3. 取出队尾的数据 ,即:返回除了第一个以外剩余的元素,可以级联使用
    println(queue1.tail) //Queue(8, 7, 6, 5)
    println(queue1.tail.tail.tail) // Queue(6, 5)

    }
    }
    ```

    > 1. Queue创建: `val queue1 = new mutable.Queue[Any]`
    > 2. Queue追加元素:
    > 1. 向队列中追加单个元素和List
    > 1. `+=`
    > 2. `++=`
    > 2. 按照进入队列的顺序删除元素(队列先进先出)`queue1.dequeue()`
    > 3. 按照队列的算法,会将数据添加到队列的最后。`queue1.enqueue(9, 8, 7)`
    > 3. Queue查看元素:
    > 1. 返回队列的第一个元素`queue1.head`
    > 2. 返回队列最后一个元素`queue1.last`
    > 3. 返回队列的尾部`queue1.tail`
    > 1. 返回除了第一个以外剩余的元素, 可以级联使用,这个在递归时使用较多。
    > 2. 也可以这样使用`queue1.tail.tail`

    ### 7. Scala映射Map

    > `HashMap 是一个散列表(数组+链表)`,它存储的内容是键值对(key-value)映射,`Java中的HashMap是无序的`,key不能重复。

    ~~~~java
    public class JavaHashMap {
    public static void main(String[] args) {

    HashMap<String, Integer> hm = new HashMap();

    hm.put("no1", 100);
    hm.put("no2", 200);
    hm.put("no3", 300);
    hm.put("no4", 400);
    hm.put("no1", 500); //更新

    // {no2=200, no1=500, no4=400, no3=300}
    System.out.println(hm);//无序的
    System.out.println(hm.get("no2"));

    }
    }
    ~~~~

    > Scala中的Map介绍:
    >
    > 1. Scala中的Map 和Java类似,也是一个散列表,它存储的内容也是键值对(key-value)映射,Scala中不可变的Map(scala.collection.immutable.Map) 是有序的,可变的Map(scala.collection.mutable.Map)是无序的。
    > 2. 构建Map的四种方式:
    > 1. Scala中的不可变Map是有序,构建Map中的元素底层是Tuple2类型。
    > 2. Scala中的可变Map是无序,构建Map中的元素底层是Tuple2类型。
    > 3. 创建空的映射 `val map = new scala.collection.mutable.HashMap[String, Int]`
    > 4. 对偶元组——即创建包含键值对的二元组, 和第一种方式等价,只是形式上不同而已。对偶元组就是只含有两个数据的元组。
    > 3. Map取值:
    > 1. 方式一:`使用map(key)`
    > 1. 如果key存在,则返回对应的值
    > 2. 如果key不存在,则抛出异常`[java.util.NoSuchElementException]`
    > 3. 在Java中,如果key不存在则返回null
    > 2. 方式二:`使用contains方法检查是否存在key`
    > 1. 如果key存在,则返回true
    > 2. 如果key不存在,则返回false
    > 3. `map.contains("B")`
    > 4. 使用containts先判断在取值,可以防止异常,并加入相应的处理逻辑
    > 3. 方式三:`使用map.get(key).get取值`
    > 1. 通过 `映射.get(键)` 这样的调用返回一个Option对象,要么是Some,要么是None
    > 2. map.get方法会将数据进行包装
    > 3. 如果 map.get(key) key存在返回some,如果key不存在,则返回None
    > 4. 如果 map.get(key).get key存在,返回key对应的值,否则,抛出异常 `java.util.NoSuchElementException: None.get`
    > 4. 方式四:`使用map.getOrElse()取值`
    > 1. 如果key存在,返回key对应的值。
    > 2. 如果key不存在,返回默认值。在java中底层有很多类似的操作。
    > 5. 如何选择取值方式建议:
    > 1. 如果我们确定map有这个key ,则应当使用map(key), 速度快
    > 2. 如果我们不能确定map是否有key ,而且有不同的业务逻辑,使用`map.contains()` 先判断在加入逻辑
    > 3. 如果只是简单的希望得到一个值,使用`map.getOrElse("ip","127.0.0.1")`

    ~~~scala
    package com.atguigu.chapter10.map

    import scala.collection.mutable

    /**
    * @Date 2021/4/1 20:33
    * @Version 10.21
    * @Author DuanChaojie
    */
    object MapDemo01 {
    def main(args: Array[String]): Unit = {
    /**
    * 1.默认map是immutable.Map
    * 2.key-value 类型支持Any
    * 3.在Map的底层,每对key-value 是Tuple2类型
    * 3.有序
    */
    val map1 = Map("dd" -> 18, "mm" -> 19, "tom" -> 22)
    println("map1 = " + map1)

    /**
    * 无序
    */
    val map2 = mutable.Map("dd" -> 18, "mm" -> 19, "tom" -> 22)
    println("map2 = " + map2)

    // 创建空的映射
    val map3 = new mutable.HashMap[String, Int]
    println("map3 = " + map3)

    /**
    * 对偶元组
    */
    val map4 = mutable.Map(("dd", 18), ("mm", 19), ("tom", 22))
    println("map4 = " + map4)

    println("------------------------Map中取值--------------------------------")

    //方式1-使用map(key)
    println(map4("dd")) // 18

    //抛出异常(java.util.NoSuchElementException: key not found:)
    //println(map4("DD"))

    //方式2-使用contains方法检查是否存在key
    if (map4.contains("dd")) {
    println("key存在,值=" + map4("dd"))
    } 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("dd").get)
    println(map4.get("DD"))
    //println(map4.get("DD").get) // 抛出异常

    //方式4-使用map4.getOrElse()取值
    println(map4.getOrElse("DD", "默认的值 鱼 <・)))><<"))
    }
    }
    ~~~

    > 4. 更新Map的元素:
    > 1. map 是可变的,才能修改,否则报错
    > 2. 如果key存在:则修改对应的值,key不存在,等价于添加一个key-val
    > 3. 增加单个元素`map += ( "D" -> 4 )`
    > 4. 增加多个元素
    > 1. `map4 += ("EE"->1, "FF"->3)`
    > 2. `val map5 = map4 + ("E"->1, "F"->3)`
    > 5. 删除Map的元素:
    > 1. `map -= ("A", "B")`
    > 2. "A","B" 就是要删除的key, 可以写多个
    > 3. 如果key存在,就删除,如果key不存在,也不会报错
    > 6. Map的遍历:
    > 1. 每遍历一次,返回的元素是`Tuple2`
    > 2. 取出的时候,可以按照元组的方式来取

    ~~~~scala
    package com.atguigu.chapter10.map

    import scala.collection.mutable

    /**
    * @Date 2021/4/1 20:45
    * @Version 10.21
    * @Author DuanChaojie
    */
    object MapDemo02 {
    def main(args: Array[String]): Unit = {
    val map5 = mutable.Map(("A", 1), ("B", "北京"), ("C", 3))
    map5("A") = 20 //修改
    println("map5=" + map5)

    map5 += ("A" -> 100) //修改
    println("map5=" + map5)

    map5 -= ("A", "B", "AAA") //删除map元素,如果没有这个key则忽略
    println("map5=" + map5)

    println("-------------map的遍历-------------------------------")
    val map6 = mutable.Map(("A", 1), ("B", "北京"), ("C", 3))

    println("----(k, v) <- map6--------")
    for ((k, v) <- map6) {
    println(k + "-" + v)
    }

    println("----k <- map6.keys--------")
    for (k <- map6.keys) {
    println(k)
    }
    println("----v <- map6.values--------")
    for (v <- map6.values) {
    println(v)
    }

    //这样取出方式 v 类型是 Tuple2
    println("----v <- map6--------")
    for (v <- map6) {
    println(v + "\t key =" + v._1 + " val=" + v._2) //v是Tuple?
    }

    }
    }
    ~~~~

    ### 8. Scala集Set

    > 1. `集是不重复元素的结合。集不保留顺序,默认是以哈希集实现。`
    > 2. java中,HashSet是实现`Set<E>`接口的一个实体类,数据是以哈希表的形式存放的,里面的不能包含重复数据。Set接口是一种不包含重复元素的 collection,HashSet中的数据也是没有顺序的。

    ~~~~java
    public class JavaHashSet {
    public static void main(String[] args) {
    // java中的Set的元素 没有顺序,不能重复
    HashSet hs = new HashSet<String>();
    hs.add("jack");
    hs.add("tom");
    hs.add("jack");
    hs.add("jack2");

    // [jack2, tom, jack]
    System.out.println(hs);

    }
    }
    ~~~~

    > 默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用 `scala.collection.mutable.Set 包`
    >
    > 1. Set的创建:
    > 1. `val set1 = Set(1, 2, 3) // 不可变`
    > 2. `val set2 = mutable.Set(1, 2, "Hello") // 可变`
    > 2. Set的元素追加:
    > 1. `set2.add("tom")`
    > 2. `set2 += 3`
    > 3. `set2.+=(4)`
    > 4. 如果添加的对象已经存在,则不会重复添加,也不会报错
    > 3. Set元素的删除:
    > 1. `set2 -= 4`
    > 2. `set2.remove("hello")`
    > 4. Set集合的遍历

    ~~~scala
    package com.atguigu.chapter10.set

    import scala.collection.mutable

    /**
    * @Date 2021/4/1 20:51
    * @Version 10.21
    * @Author DuanChaojie
    */
    object SetDemo01 {
    def main(args: Array[String]): Unit = {
    val set1 = Set(1, 2, 3) // 不可变
    println("set1 = " + set1)
    println("set1.max = " + set1.max)
    println("set1 min = " + (set1 min))

    val set2 = mutable.Set(1, 2, "Hello") // 可变
    println("set2 = " + set2)

    println("-------------Set添加元素--------------------")
    // 添加元素的三种方式
    set2.add("tom")
    set2 += 3
    set2.+=(4)
    // set2 = Set(1, 2, 3, tom, 4, Hello)
    println("set2 = " + set2)
    println("-------------Set删除元素--------------------")

    set2 -= 4
    println("set2 = " + set2)
    // 方法的形式,scala的Set可以直接删除值
    // 如果删除的对象不存在,则不生效,也不报错
    set2.remove("hello")
    println("set2 = " + set2)

    println("-------------Set集合遍历--------------------")
    for (item <- set2) {
    println(item)
    }
    }
    }
    ~~~

    > 集Set的更多操作:
    >
    > ![image-20210401231809623](assets/image-20210401231809623.png)
    >
    > 查看Scala其它集合的更多使用方法,可以查看相关的文档。

    ## ☆

  • 相关阅读:
    P2351 [SDOI2012]吊灯
    洛谷P1450 [HAOI2008]硬币购物 背包+容斥
    P5110 块速递推-光速幂、斐波那契数列通项
    AT2304 Cleaning
    CSP-S 2020
    CF487E Tourists
    P4334 [COI2007] Policija
    动态逆序对专练
    CF437D The Child and Zoo
    CF1032G Chattering
  • 原文地址:https://www.cnblogs.com/huaobin/p/15764423.html
Copyright © 2011-2022 走看看