Scala-集合类型实践

集合

Scala 的集合有三大类:序列 Seq、集 Set、映射 Map,所有的集合都扩展自 Iterable特质。

对于几乎所有的集合类,Scala 都同时提供了可变和不可变的版本,分别位于以下两个包中

不可变集合:scala.collection.immutable

可变集合: scala.collection.mutable

Scala 不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而不会对原对象进行修改。类似于 java 中的 String 对象

可变集合,就是这个集合可以直接对原对象进行修改,而不会返回新的对象。类似于 java 中 StringBuilder 对象

建议:在操作集合的时候,不可变用符号,可变用方法

不可变集合类型
Scala-集合类型实践_第1张图片

其中蓝色是具体的class,绿色是trait。

1)Set、Map 是 Java 中也有的集合

2)Seq 是 Java 没有的,我们发现 List 归属到 Seq 了,因此这里的 List 就和 Java 不是同一个概念了

3)我们前面的 for 循环有一个 1 to 3,就是 IndexedSeq 下的 Range

4)String 也是属于 IndexedSeq,String和Array是通过隐式转换成了IndexedSeq

5)我们发现经典的数据结构比如 Queue 和 Stack 被归属到 LinearSeq(线性序列)

6)注意 Scala 中的 Map 体系有一个 SortedMap,说明 Scala 的 Map 可以支持排序

7)IndexedSeq 和 LinearSeq 的区别:

a、IndexedSeq 是通过索引来查找和定位,因此速度快,比如 String 就是一个索引集合,通过索引即可定位

b、LinearSeq 是线型的,即有头尾的概念,这种数据结构一般是通过遍历来查找

可变集合类型

Scala-集合类型实践_第2张图片

数组

不可变数组

第一种方式定义数组

val arr1 = new Array[Int](10)

(1)new 是关键字

(2)[Int]是指定可以存放的数据类型,如果希望存放任意数据类型,则指定 Any

(3)(10)表示数组的大小,确定后就不可以变化

第二种方式定义数组

val arr1 = Array(1, 2)

(1)在定义数组时,直接赋初始值

(2)使用 apply 方法创建数组对象

object TestImmutableArray {

    def main(args: Array[String]): Unit = {
        // 1、创建数组
        val arr = new Array[Int](5)

        // 2、另一种创建的方式
        val arr2 = Array(14, 56, 78)

        // 3、访问数组的元素
        println(arr(0)) // 0
        println(arr(4)) // 0
//        println(arr(5)) error
        arr(0) = 1
        arr(4) = 109
        println(arr(0)) // 1
        println(arr(4)) // 109

        // 4、数组遍历
        // 4.1、普通for循环
        // 相当与for (i <- 0 until arr.length)
        for (i <- arr.indices) {
            println(arr(i))
        }

        // 4.2、直接遍历所有元素,增强for循环
        for (elem <- arr2) {
            println(elem)
        }

        // 4.3、迭代器的使用
        val iter = arr2.iterator
        while (iter.hasNext) {
            println(iter.next())
        }

        // 4.4、调用foreach方法
        arr2.foreach((elem: Int) => {
            println(elem)
        })
        // 简写
        arr.foreach(println)

        println(arr2.mkString("--")) // 14--56--78

        // 5、添加元素
        val newArr = arr2.:+(35)        // :+()从数组后面追加一个元素,并返回新的数组
        println(arr2.mkString("--"))    // 14--56--78
        println(newArr.mkString("--"))  // 14--56--78--35

        val newArr2 = newArr.+:(98)     // +:()从数组前面追加一个元素,并返回新的数组
        println(newArr2.mkString("--")) // 98--14--56--78--35

        val newArr3 = newArr2 :+ 15
        val newArr4 = 19 +: 15 +: newArr3 :+ 67    // 如果是以:结尾的话,需要更换位置
        println(newArr4.mkString(","))  // 19,15,98,14,56,78,35,15,67
    }
}

可变数组

定义变长数组

 val arr01 = ArrayBuffer[Any](3, 2, 5)

(1)[Any]存放任意数据类型

(2)(3, 2, 5)初始化好的三个元素

(3)ArrayBuffer 需要引入 scala.collection.mutable.ArrayBuffer

(4)ArrayBuffer 是有序的集合

(5)增加元素使用的是 append 方法(),支持可变参数

可变数组和不可变数组的转换

arr1.toBuffer //不可变数组转可变数组,返回结果才是一个可变数组,arr1 本身没有变化
arr2.toArray //可变数组转不可变数组,返回结果才是一个不可变数组,arr2 本身没有变化
object TestArrayBuffer {

    def main(args: Array[String]): Unit = {
        // 1、创建一个可变数组
        val arr1 = new ArrayBuffer[Int]()
        val arr2 = ArrayBuffer(1, 3, 46, 7)

        println(arr1.mkString(",")) // 无数据
        println(arr2)               // ArrayBuffer(1, 3, 46, 7)
        println(arr2.toString())    // ArrayBuffer(1, 3, 46, 7)

        // 2、访问数组中的元素
//        println(arr1(0)) // error
        println(arr2(1))
        arr2(2) = 17
        println(arr2(1))

        // 3、添加元素
        val newArr1 = arr1 :+ 15   // :+是针对不可变数组的添加元素的
        println(newArr1)  // ArrayBuffer(15)
        println(arr1)     // ArrayBuffer()

        val newArr2 = arr1 += 19   // 这里是把arr1的地址给newArr2了,因此不推荐把可变数组处理的结果赋值给别的
        println(arr1)              // ArrayBuffer(19)
        println(newArr2)           // ArrayBuffer(19)
        println(newArr2 == arr1)   // true

        77 +=: arr1
        println(arr1)             // ArrayBuffer(77, 19)

        arr1.append(36)
        arr1.prepend(45, 88)
        arr1.insert(1, 99999, 1000)
        println(arr1)             // ArrayBuffer(45, 99999, 1000, 88, 77, 19, 36)

        arr1.insertAll(2, newArr1)
        arr1.appendAll(newArr1)
        arr1.prependAll(newArr1)
        println(arr1)             // ArrayBuffer(15, 45, 99999, 15, 1000, 88, 77, 19, 36, 15)

        // 对于不可变数组推荐使用 :+ 和 +: 来进行处理
        // 对于可变数组推荐使用方法来处理

        // 4、删除元素
        arr1.remove(1)
        println(arr1)             // ArrayBuffer(15, 99999, 15, 1000, 88, 77, 19, 36, 15)

        arr1.remove(1, 2)
        println(arr1)             // ArrayBuffer(15, 1000, 88, 77, 19, 36, 15)

        arr1 -= 77
        println(arr1)             // ArrayBuffer(15, 1000, 88, 19, 36, 15)

        arr1 -= 888
        println(arr1)             // ArrayBuffer(15, 1000, 88, 19, 36, 15)
        
        // 5、可变数组转换成不可变数组
        val arr: ArrayBuffer[Int] = ArrayBuffer(23, 45, 67)
        val newArr: Array[Int] = arr.toArray
        println(newArr.mkString(",")) // 23,45,67
        println(arr)                  // ArrayBuffer(23, 45, 67)

        // 6、不可变数组转换为可变数组
        val buffer: mutable.Buffer[Int] = newArr.toBuffer
        println(buffer) // ArrayBuffer(23, 45, 67)
        println(newArr) // [I@6b2fad11
        println(newArr.mkString(",")) // 23,45,67
    }
}

在大数据的处理过程中,如果用到了数组的话,推荐使用不可变数组进行操作,并且能用不可变就用不可变。

多维数组

多维数组定义

val arr = Array.ofDim[Double](3,4)

说明:二维数组中有三个一维数组,每个一维数组中有四个元素

object TestMulArray {

    def main(args: Array[String]): Unit = {
        // 1、创建一个二位数组
        val array: Array[Array[Int]] = Array.ofDim[Int](2, 3)

        // 2、访问元素
        array(0)(2) = 9
        array(1)(0) = 25

        for (i <- 0 until array.length; j <- 0 until array(i).length) {
            println(array(i)(j))
        }
        for (i <- array.indices; j <- array(i).indices) {
            print(array(i)(j) + "\t")
            if (j == array(i).length - 1) println()
        }

        array.foreach(line => line.foreach(println))
        // 简写
        array.foreach(_.foreach(println))
    }
}

列表List

不可变列表

object TestList {

    def main(args: Array[String]): Unit = {
        // (1)List 默认为不可变集合
        // (2)创建一个 List(数据有顺序,可重复)
        val list1 = List(23, 56, 89)
        println(list1) // List(23, 56, 89)

        println(list1(1))
//        list1(1) = 12 // error

        // (3)遍历 List
        list1.foreach(println)

        // (4)List 增加数据
        val list2 = list1 :+ 10
        val list3 = 10 +: list1
        println(list1) // List(23, 56, 89)
        println(list2) // List(23, 56, 89, 10)
        println(list3) // List(10, 23, 56, 89)

        val list4 = list2.::(51)
        println(list2) // List(23, 56, 89, 10)
        println(list4) // List(51, 23, 56, 89, 10)

        // 空集合 Nil
        val list5 = Nil.::(13)
        println(list5)  // List(13)

        val list6 = 42 :: 56 :: 44 :: Nil
        println(list6)  // List(42, 56, 44)

        // (5)集合间合并:将一个整体拆成一个一个的个体,称为扁平化
        val list7 = list5 :: list6
        println(list7)  // List(List(13), 42, 56, 44)

        val list9 = list5 ::: list6
        println(list9)  // List(13, 42, 56, 44)

        val list10 = list5 ++ list6
        println(list10)  // List(13, 42, 56, 44)
    }
}

可变列表

object TestListBuffer {

    def main(args: Array[String]): Unit = {
        // 1、创建可变列表
        val list1 = new ListBuffer[Int]()
        val list2 = ListBuffer(12, 34, 56)

        println(list1) // ListBuffer()
        println(list2) // ListBuffer(12, 34, 56)

        // 2、添加元素
        list1.append(12, 45)
        list2.prepend(45, 67)
        list1.insert(1, 19, 44)

        println(list1) // ListBuffer(12, 19, 44, 45)
        println(list2) // ListBuffer(45, 67, 12, 34, 56)

        31 +=: 24 +=: list1 += 35 += 44 += 11
        println(list1) // ListBuffer(31, 24, 12, 19, 44, 45, 35, 44, 11)

        // 3、合并list
        val list3 = list1 ++ list2
        println(list1) // ListBuffer(31, 24, 12, 19, 44, 45, 35, 44, 11)
        println(list2) // ListBuffer(45, 67, 12, 34, 56)
        println(list3) // ListBuffer(31, 24, 12, 19, 44, 45, 35, 44, 11, 45, 67, 12, 34, 56)

        list1 ++= list2
        println(list1) // ListBuffer(31, 24, 12, 19, 44, 45, 35, 44, 11, 45, 67, 12, 34, 56)
        println(list2) // ListBuffer(45, 67, 12, 34, 56)

        val list4 = ListBuffer(1, 2, 3)
        list4 ++=: list2
        println(list4) // ListBuffer(1, 2, 3)
        println(list2) // ListBuffer(1, 2, 3, 45, 67, 12, 34, 56)

        // 4、修改元素
        list2(3) = 444
        list2.update(0, 111)
        println(list2) // ListBuffer(111, 2, 3, 444, 67, 12, 34, 56)

        // 5、删除元素
        list2.remove(0)
        list2 -= 67
        println(list2) // ListBuffer(2, 3, 444, 12, 34, 56)
    }
}

Set集合

默 认 情 况 下 , Scala 使 用 的 是 不 可 变 集 合 , 如 果 你 想 使 用 可 变 集 合 , 需 要 引 用scala.collection.mutable.Set 包

不可变Set

Set 默认是不可变集合,数据无序,数据不可重复,因此可以使用Set来进行数据的去重。

object TestImmutableSet {

    def main(args: Array[String]): Unit = {
        // 1、创建一个Set
        val set1 = Set(13, 45, 13, 45, 67, 8)
        println(set1) // Set(13, 45, 67, 8)

        // 2、添加元素
        val set2 = set1 + 44
        println(set1) // Set(13, 45, 67, 8)
        println(set2) // Set(13, 45, 44, 67, 8)

        // 3、合并Set
        val set3 = Set(13, 45, 13, 99, 77)
        val set4 = set2 ++ set3
        println(set2) // Set(13, 45, 44, 67, 8)
        println(set3) // Set(13, 45, 99, 77)
        println(set4) // Set(77, 13, 45, 44, 67, 99, 8)

        // 4、删除元素
        val set5 = set3 - 13
        println(set3) // Set(13, 45, 99, 77)
        println(set5) // Set(45, 99, 77)
    }
}

可变mutable.Set

object TestMutableSet {

    def main(args: Array[String]): Unit = {
        // 1、创建一个Set
        val set1 = mutable.Set(13, 45, 13, 45, 67, 8)
        println(set1) // Set(13, 45, 67, 8)

        // 2、添加元素
        val set2 = set1 + 11
        println(set1) // Set(13, 45, 67, 8)
        println(set2) // Set(13, 45, 67, 11, 8)

        set1 += 12
        println(set1) // Set(13, 12, 45, 67, 8)

        val flag1 = set1.add(123)
        println(flag1) // true
        println(set1) // Set(13, 12, 123, 45, 67, 8)
        val flag2 = set1.add(123)
        println(flag2) // false
        println(set1) // Set(13, 12, 123, 45, 67, 8)

        // 3、删除元素
        set1 -= 12
        val flag3 = set1.remove(13)
        println(set1) // Set(45, 67, 123, 8)
        val flag4 = set1.remove(13)
        println(set1) // Set(45, 67, 123, 8)

        // 4、合并两个Set
        val set3 = mutable.Set(13, 45, 13, 44, 77)
        val set4 = set1 ++ set3
        println(set1) // Set(45, 67, 123, 8)
        println(set3) // Set(45, 13, 44, 77)
        println(set4) // Set(45, 67, 13, 123, 8, 44, 77)
        set1 ++= set3
        println(set1) // Set(45, 67, 13, 123, 8, 44, 77)
        println(set3) // Set(45, 13, 44, 77)
    }
}

Map集合

Scala 中的 Map 和 Java 类似, 也是一个散列表,它存储的内容也是键值对(key-value)映射

不可变Map

object TestImmutableMap {

    def main(args: Array[String]): Unit = {
        // 1、创建map
        val map1: Map[String, Int] = Map("a" -> 13, "b" -> 56, "hello" -> 8)
        println(map1)          // Map(a -> 13, b -> 56, hello -> 8)
        println(map1.getClass) // class scala.collection.immutable.Map$Map3 3是3个元素

        // 2、遍历元素
        map1.foreach(println)
//        (a,13)
//        (b,56)
//        (hello,8)
        map1.foreach((kv: (String, Int)) => println(kv))

        // 3、取map所有的key 或者value
        for (key <- map1.keys) {
            println(s"key is $key, value is ${map1.get(key)}")
//            key is a, value is Some(13)
//            key is b, value is Some(56)
//            key is hello, value is Some(8)
        }

        // 4、访问某一个key的value
        println("a: " + map1.get("a").get)        // a: 13,这个写法不够安全
        println("a: " + map1.getOrElse("a", "0")) // a: 13
//        println("c: " + map1.get("c").get)        // 这里会报错
        println("c: " + map1.get("c"))            // c: None
        println("c: " + map1.getOrElse("c", 0))   // c: 0

        println("a: " + map1("a"))                // a: 13,这个等于map1.get("a").get
    }
}

可变Map

object TestMutableMap {

    def main(args: Array[String]): Unit = {
        // 1、创建map
        val map1: mutable.Map[String, Int] = mutable.Map("a" -> 13, "b" -> 56, "hello" -> 8)
        println(map1)          // Map(a -> 13, b -> 56, hello -> 8)
        println(map1.getClass) // class scala.collection.mutable.HashMap

        // 2、添加元素
        map1.put("c", 54)
        map1.update("d", 3)
        println(map1)          // Map(b -> 56, d -> 3, a -> 13, c -> 54, hello -> 8)

        map1 += (("e",13))
        println(map1)          // Map(e -> 13, b -> 56, d -> 3, a -> 13, c -> 54, hello -> 8)

        // 3、删除元素
        map1.remove("c")
        println(map1.getOrElse("c", -1)) // -1
        map1 -= "d"
        println(map1)          // Map(e -> 13, b -> 56, a -> 13, hello -> 8)

        // 4、修改元素=插入元素
        map1.put("c", 54)
        map1.update("d", 3)
        println(map1)          // Map(e -> 13, b -> 56, d -> 3, a -> 13, c -> 54, hello -> 8)

        // 5、合并两个Map
        val map2: Map[String, Int] = Map("a" -> 33, "test" -> 19)
        map1 ++= map2    // 添加并覆盖
        println(map1)    // Map(e -> 13, b -> 56, d -> 3, a -> 33, c -> 54, hello -> 8, test -> 19)
        println(map2)    // Map(a -> 33, test -> 19)

        val map4: Map[String, Int] = Map("e" -> 999, "map" -> 77)
        val map3: Map[String, Int] = map4 ++ map1
        println(map3) // Map(e -> 13, test -> 19, map -> 77, a -> 33, b -> 56, c -> 54, hello -> 8, d -> 3)

    }
}

元组

元组也是可以理解为一个容器,可以存放各种相同或不同类型的数据。说的简单点,就是将多个无关的数据封装为一个整体,称为元组,即元素的组合。

注意:元组中最大只能有 22 个元素。

object TestTuple {

    def main(args: Array[String]): Unit = {
        // 1、创建元祖
        val tuple: (String, Int, Char, Boolean) = ("hello", 100, 'a', true)
        println(tuple) // (hello,100,a,true)

        // 2、访问元组
        println(tuple._1) // hello
        println(tuple._2) // 100
        println(tuple._3) // a
        println(tuple._4) // true

        println(tuple.productElement(1)) // 100

        // 3、遍历元组数据
        for (elem <- tuple.productIterator) {
            println(elem)
        }

        // 4、嵌套元组
        val mulTuple = (12, 0.3, "hello", (0, "scala"), 99)

        println(mulTuple._4._2) // scala
    }
}

队列

Scala 也提供了队列(Queue)的数据结构,队列的特点就是先进先出。进队和出队的方法分别为 enqueue 和 dequeue。

object TestQueue {

    def main(args: Array[String]): Unit = {
        // 创建一个可变的队列
        val queue = new mutable.Queue[String]()

        queue.enqueue("a", "b", "hello") // Queue(a, b, hello)

        println(queue)            // a
        println(queue.dequeue())  // Queue(b, hello)
        println(queue)            // b
        println(queue.dequeue())  // Queue(hello)
        println(queue)

        // 不可变队列
        val queue2 = Queue("a", "b", "hello")
        val queue3 = queue2.enqueue("d")
        println(queue2) // Queue(a, b, hello)
        println(queue3) // Queue(a, b, hello, d)
    }
}

并行集合

Scala 为了充分使用多核 CPU,提供了并行集合(有别于前面的串行集合),用于多核环境的并行计算。

object TestParallel {

    def main(args: Array[String]): Unit = {

        val result = (1 to 100).map(
            x => Thread.currentThread().getId
        )
        println(result) // 都是1

        val result2 = (1 to 100).par.map(
            x => Thread.currentThread().getId
        )
        println(result2) // 有很多不一样的线程id
        // ParVector(10, 10, 10, 10, 10, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 12, 12, 12, 13, 13, 13, 14, 14, 14, 14, 14, 14, 15, 15, 15, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13)
    }
}

你可能感兴趣的:(scala)