五, Scala常见集合类总结(Array, List, Set, Map)

五, Scala常见集合类总结(Array, List, Set, Map)

5.1 Scala集合概述

  1. Scala 的集合有三大类: 序列seq, 集Set, 映射Map, 所有的集合都扩展自 Iterable 特质;
  2. 对于几乎所有的集合类, Scala都同时提供了可变不可变的版本. 分别位于以下两个包: scala.collection.immutable, scala.collection.mutable

Q:什么是可变,不可变集合?
a. Scala 不可变集合, 就是指该集合对象不可修改, 每次修改就会返回一个新的对象引用, 而不会对原对象数据进行修改, 类似于java中的String对象, (改变对象的引用地址, 而不是直接修改原有引用地址中的数据)
b. Scala 可变集合, 指的是可以直接对原有的集合对象进行修改, 而不会返回新的对象, (类似于java中的StringBuffer对象)

  1. 在操作集合的时候, 推荐不可变用符号, 可变用方法(先记住这句话)

5.1.1 Scala 不可变集合继承图

在这里插入图片描述

  • Seq 可细分为索引序列(indexed)线性序列(indexed)。一般来说索引序列的访问速度比线性序列要快一些,但是线性序列的应用场景比较多,比如队列和栈等都是很常用的数据结构。
  • SetMap 都提供有序方式的集合 SortedXXX 。Java 中 List 归属于 Set 集合下,在 Scala 则属于 Seq 的线性序列部分。
  • String 被归纳到了索引序列下:因为它本质上可被认作是 Char[] 类型集合,并且还可以通过索引的方式来输出对应位置的字符。

5.1.2 Scala 可变集合继承图

在这里插入图片描述

  • 可变集合的内容明显要比不可变集合要更复杂一些,主要是多了 Buffer (缓冲)的内容。在实际开发中我们常用的有 ArrayBufferListBuffer

  • 如果涉及到线程安全的内容,则使用以 Synchronized 作为前缀的集合。

5.2 数组 Array

  • 数组是有序的,可以包含重复项,不可变(Array)或可变(ArrayBuffer)

5.2.1 不可变数组

[定义方法]

两种定义方法解释
val arr1 = new ArrayInt 1. new 是关键字; 2. [Int] 指定数组存放数据类型(泛型), [Any] 为任意类型; 3. (10) 表示数组的大小, 确定后不可变
val arr2 = Array(1,2) 1. 定义数组时, 直接赋初始值; 2. 使用apply方法创建数组对象

中括号[]表示泛型, 圆括号()表示数组长度

[不可变数组的增删改查和遍历方法]

写法解释
arr(index)根据索引访问数组arr的元素
:+ 尾部追加, +: 头部追加, ++ 连接两个集合, +++ 连接两个List 向集合中追加元素, 会生成新的数组, 冒号始终靠近集合变量一端
arr.drop(index) 根据索引删除数组arr的元素, 会生成新的数组
arr.update(index, newNum) 或者 arr(index) = newNum根据索引修改数组arr的元素, 会生成新的数组
arr.reverse反转整个数组, 会生成新的数组

不可变数组的遍历方法:

1.普通遍历(增强for循环), for(i <- arr) print(i)
2.索引遍历(indices), for(i <- arr.indices) print(arr(i))
3.迭代器遍历(arr.iterator), val it = arr.iterator it.hasNext print(it.next)
4.使用mkString方法, print(arr.mkString()
5.使用foreach方法, arr.foreach((elem: Int) => {print(elem)}) 可化简为: arr.foreach(elem => print)

补充: indices实际上是一个封装起来的函数:

 /** Produces the range of all indices of this sequence.
   *
   *  @return  a `Range` value from `0` to one less than the length of this $coll.
   */
  def indices: Range = 0 until length

[案例实操]

package ImMutableArrayDemo

object ArrayTest {
  def main(args: Array[String]): Unit = {
   //1. 创建不可变数组方式1
   //val arr:Array[Int] = new Array[Int](5)
    val arr = new Array[Int](5)
    //1. 创建不可变数组方式2
    val arr1 = Array(2,3,4,5,6)
    var arr3 = Array(2,3,false, "sbareu", 'a', 5.6)

    println(arr)
    //1.0 不可变数组- 访问某一元素, 直接索引访问
    println(arr(2) + ',' + arr(3))

    ///1.1 不可变数组-增加元素 (由于是不可变数组, 所以增加元素时, 生成了新的数组,
    //  可以看到地址值不相同)
    // :+ 向集合的尾部追加元素, +: 头部追加
    // ++ 连接前后两个集合 ::: 连接前后两个List
    // 注意:    :  冒号始终靠近集合变量这一端
    val ints:Array[Int] = arr :+ 88  //尾部追加
    val intsa:Array[Int] = 88 +: arr //头部追加
    val intsb = 77 +: 88 +: arr :+ 22 //连续追加
    var intsc: Array[Int] = arr ++ Array(2,3,4,2) //集合追加


    ///1.2 不可变数组-删除元素
    arr.update(2,8)
    println(ints.mkString(","))
    val ints1 = ints.drop(2)
    println(ints1.mkString(","))
    
    ///1.3 不可变数组-修改元素, 两种方式, 1. 索引直接修改, 2. 数组.update(index, num)
    arr(2) = 2
    arr.update(3,3)

    ///1.4 不可变数组-遍历元素
    //1.4.1 普通遍历
    for( i <- arr) print(i + ", ")
    println()
    / arr.indices 是返回数组的所有索引值!!,
    // 所以下面的for循环是遍历的索引值
    for( i <- arr.indices) print( arr(i) + ", ")
    println()

    /1.4.2 简化遍历(即增强for循环, for(容器内元素变量 <- 容器))
    //直接遍历所有元素, 不考虑索引
    for(elem <- arr) print(elem + ", ")
    println()

    /1.4.3 迭代器遍历
    val it = arr.iterator
    while(it.hasNext){
      print(it.next() + ", ")
    }
    println()

    /1.4.4 调用foreach方法遍历
    //   复习: Scala匿名函数写法 (参数列表) => {函数体}
    arr.foreach((elem: Int) => {print(elem + ", ")})
    //化简: arr.foreach(elem => print(elem + ", "))
    //再化简 arr.foreach(print)
    println()

    /1.4.5 遍历数组, 并添加连字符
    val str = arr.mkString("--")
    println(str)

    println("==========================================")

    for(i <- arr3){
      print(i + ", ")
    }
  }
}

补充: 为什么Scala中Array(num)等同于 new Array(num) ?
在这里插入图片描述

5.2.2 可变数组

[基本语法]

var arrBuf = ArrayBufferAny

  1. [Any]存放任意数据类型;
  2. (1,2,3,4,5) 为初始化好的三个元素, 也可以把括号放空;
  3. ArrayBuffer 需要引入 scala.collection.mutable.ArrayBuffer;

[常用增删改方法]

写法解释
arrBuf(index)根据索引访问可变数组arrBuf的元素, print(arrBuf)中, 默认会调用可变数组类ArrayBuffer的toString方法
arrBuf.append 或 += 向集合的尾部追加元素
arrBuf.prepend 或 +=: 向集合的头部追加元素,冒号始终靠近集合变量一端
arrBuf.insert(index, Any*)向集合的指定索引处插入任意个元素
arrBuf.remove(index, count) 或 -=删除数组arr指定索引后的count个元素
arrBuf.update(index, newNum) 或者 arrBuf(index) = newNum根据索引修改数组arr的元素

[案例实操]

package mutableArraydemo

import scala.collection.mutable.ArrayBuffer

object MutableArrayTest {
  def main(args: Array[String]): Unit = {
    
    //可变数组的创建初始化
    //val arrBuf:ArrayBuffer[Int] = new ArrayBuffer[Int](5)
    val arrBuf = new ArrayBuffer[Int]()
    val arrBuf1 = ArrayBuffer[Any](1,3,5,7,8)

    //访问
    println(arrBuf1)   //隐式的调用了toString()
    print(arrBuf1(2))
    println()
    //向后追加元素  append +=
    //头部追加 prepend +=:
    arrBuf1.append(6,9,11)

    print(arrBuf1.mkString("-"))

    println()
    //插入元素  insert
    arrBuf1.insert(3,6)
    print(arrBuf1.mkString("-"))

    println()
    //修改元素  arr(index)    .update
    arrBuf1(1) = 2
    arrBuf1.update(0, 88)
    print(arrBuf1.mkString("-"))

    println()
    //删除元素 remove  -=
    arrBuf1.remove(0)
    arrBuf1 -= 11  //删除指定元素
    print(arrBuf1.mkString("-"))

    println()
    //反转元素 reverse


    print(arrBuf1.reverse.mkString("-"))

    println()

    //遍历集合(跟不可变数组的遍历方式完全一致)
    //1. mkString
    //2. for( i <- 集合)
    //3. iterator
    //4. 集合.indices  遍历索引
    //5. 集合.foreach(elem => print)
  }
}

5.2.3 不可变数组与可变数组的转换

[基本语法]

语法解释
arr.toBuffer不可变数组转为可变数组(toBuffer), 返回的是一个可变数组, arr不会变化的噢!
arr.toArray可变数组转为不可变数组(toArray), 返回的是一个不可变数组, arr不会变化的噢!

[案例实操]

在这里插入图片描述

5.2.4 多维数组

[基本语法]

val arr = Array.ofDim[T](一维数组的个数, 一维数组的元素数)

  • 如: val arr = Array.ofDimDouble
    • 说明:二维Double数组中(三行四列)有三个一维数组,每个一维数组中有四个元素

[案例实操]

在这里插入图片描述

  • 几维数组几个foreach

5.3 列表List

  • 列表是有序的, 可以包含重复项, 可变(List)或不可变(List)
  • 没有索引的线性序列

5.3.1 不可变 List

[基本语法]

  1. 创建
    val list: List[T] = List()
  1. 访问
    1. 直接打印 print(list)
    2. 索引访问 print(list(index))

[案例实操]

//定义一个list, 并访问
val list = List(1,2,3,4,5) //注意. List不存在new方式创建对象

print(list) //List中重写了toString(),可以直接打印

print(list(2)) //list(index), list可以通过索引访问

//创建一个空集合,Nil是一个独立的类,它继承于List[Nothing].
val nil: Nil.type = Nil
//打印Nil会打印List()
println(nil)

5.3.1.1 头,尾追加元素(:+ :+)

  1. 借助+:, :+, 可以向List中添加元素

由于 List 本身是不可改变的,因此追加操作不会改变原来的 List ,而是返回一个新的 List。Scala 的 List 提供操作符号来表示追加,比如头插入 +: 和尾部追加 :+
`

//在列表后面追加元素,使用函数 :+ ,且 list 写在前面。
val addTohead: List[Int] = list :+ 0

//在列表前面追加元素,使用函数 +: ,且 list 写在后面。
val addToTail: List[Int] = 6 +: list

5.3.1.2 拼接List ::

  1. 借助:: 来整体拼接多个List(List会被当做是一个整体)

除了头部插入,尾部插入之外,使用 :: 符号可以实现将多个零散的元素拼接到 List 当中。

在这里插入图片描述

5.3.1.2 扁平化拼接List :::

在这里插入图片描述

扁平化(flat): 讲一个整体拆成一个一个的个体, 称为扁平化;

5.3.2 可变 ListBuffer

在这里插入图片描述

在这里插入图片描述

5.4 集合 Set

  • 集合无序, 不可以包含重复项
  • Scala中的Set同样分为可变(mutable)和 不可变(immutable)的, 默认情况下是不可变的;
//创建一个不可变的Set集合。
val immutableInts = Set(1,2,3,4)

//创建一个可变的Set集合。
val mutableInts = mutable.Set(1,2,3,4,5)

5.4.1 向Set中添加元素

在这里插入图片描述

5.4.2 移除Set内的元素

在这里插入图片描述

5.4.3 Set集合的常用方法

在这里插入图片描述

5.5 集合 Map

  • 与Java的Map类似, 散列表, 存储内容为键值对
  • 可变Map无序, 不可变Map有序, 键key均不可重复

在这里插入图片描述

不可变 Map的常见操作

package mapdemo

object ImutableDemo {
  //不可变Map
  def main(args: Array[String]): Unit = {
    val map: Map[String, Int] = Map("xiaoming" -> 18, ("xiaowang", 22), "xiaogou" -> 30)

    //访问数据,
    //1. 获取key, map.keys, 通过key获取值
    for(key <- map.keys){
      println(s"key: ${key}, value: ${map.get(key)}" )
    }
    //Q: 为什么上面的遍历返回了Some?

    //1.1. get(key),如果遇到value无值在呢么办?
    val maybeInt: Option[Int] = map.get("xiaowu")
    println(maybeInt)
    //Q: Option是什么?
     //1.2. getOrElse
    println(map.getOrElse("xiaoliu", -1))

    //2. 遍历map
    map.foreach((kv) => {println(kv)})

    println("========")
    //3. map 添加新的键值对, map + ((k1, v1), (k2, v2)), 会生成新的map对象
    val map2 = map.+(("xiaozhou", 27))

    //4. map删除键值对, 会生成新的map对象
    val map3 = map2.-("xiaogou")

    map3.foreach((kv) => {println(kv)})

  }
}

可变Map的常见操作

package mapdemo

import scala.collection.mutable

object MutableMapDemo {
  def main(args: Array[String]): Unit = {
    //1. 创建可变的map对象
    val map: mutable.Map[String, Int] = mutable.Map("xiaogou" -> 26, ("xiaosan", 13), ("xiaochen", 18))

    //2. 获取key,   map.keys
    for (key <- map.keys) {
      println(s"KEY: ${key}, VALUE: ${map.get(key)}")

    }

    //  map.getOrElse
    println(s"KEY: asd, VALUE: ${map.getOrElse("asd", "no data")}")

    //3. 可变map增加键值对    += 或 put(key, value)
    val map1: mutable.Map[String, Int] = map + (("xiaosi", 28))
    map1.foreach((kv) => print(kv + "; "))

    println()
    map += ("xiaoming" -> 35)
    map.put("wangwu", 35)

    map.foreach((kv) => print(kv + "; "))

    //4. 可变Map删除指定键值对 -=
    println()
    map -= ("xiaogou")
    map.foreach((kv) => print(kv + "; "))

    //5. 可变map修改指定key的值  update() 或 直接赋值 map(key) = newValue
    println()
    map.update("wangwu", 48)
    map.foreach((kv) => print(kv + "; "))
  }
}

5.5.2 根据Key取出Map内的value

在这里插入图片描述

5.5.3 使用 contains 方法检查 key 是否存在

在这里插入图片描述

5.5.4 使用 get 方法避免异常

在这里插入图片描述

5.5.5 简洁的 getOrElse 方法

在这里插入图片描述

5.5.6 如何选择这几种取值方式

在这里插入图片描述

5.5.7 对Map的增删改查

  • 见上方代码示例, 待凝练

5.5.8 对Map的遍历

在这里插入图片描述

5.6 元组 Tuple

5.8 队列 Queue

  • 待补充

参考文章:

  1. Scala 编程
  2. scala 集合
posted @ 2022-05-26 20:30  青松城  阅读(327)  评论(0)    收藏  举报