scala的集合

张裕  金牌会员 | 2025-3-12 21:41:55 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 676|帖子 676|积分 2028

scala的集合体系的区分了可变( mutable  )和不可变(immutable )集合。

mkString(seq:String):方法是将原字符串使用特定的字符串seq分割。

mkString(statrt:String,seq:String,end:String):方法是将原字符串使用特定的字符串seq分割的同时,在原字符串之前添加字符串start,在厥后添加字符串end。

  1.     var str0 = "scala"
  2.     println(str0.mkString(",")) //separate string with comma
  3.     println(str0.mkString("begin", ",", "end"))
  4.     val a = List(1,2,3,4)
  5.     val b = new StringBuilder()
  6.     println(a.mkString("List(" , "- " , ")"))
复制代码
输特别式:
  1. s,c,a,l,a
  2. begins,c,a,l,aend
  3. List(1- 2- 3- 4)
复制代码
备注:集合中的大部分都存在(指名字相同的类分别存在)三个包中:collection、mutable、immutable,只有trait Buffer只存在mutable集合中


不可变数组Array

与Java中不同的是,Scala中没有数组这一种范例。在Scala中,Array类的功能就与数组类似。与所有数组一样,Array的长度不可变,内里的数据可以按索引位置访问

备注Array是在scala包下,而不是在scala.collection包下

  1.     //第一种构造:指定泛型,指定长度
  2.     val array1 = new Array[Int](5)
  3.     array1(1) = 1 // 实际上调用的是实例对象update方法,等价arr1.update(1,1)
  4.     println(array1(1))
  5.     //第二种构造:初始化元素,可以是任意类型,实质是隐式调用apply方法
  6.     val array2 = Array(0, 1, 2, 3, 4)
  7.     println(array2(3))
  8.     //增加元素(由于创建的是不可变数组,增加元素,其实是产生新的数组)
  9.     val ints: Array[Int] = array1 :+ 5 //元素加在数组最后面 巧记::写在集合的那一侧
  10.     val newArr3 = 15 +: array2 //元素加在数组最前面
  11.     val newArr4 = 19 +: 29 +: newArr3 :+ 26 :+ 73    // 19,29,15,0,1,2,3,4,26,73
  12.     println(newArr4.mkString(","))
  13.     // 数组的遍历
  14.     // 第一种方式
  15.     for (i <- 0 until array1.length) {
  16.       println(array1(i))
  17.     }
  18.     // 第二种方式
  19.     for (i <- array1.indices) println(array1(i))
  20.     // 第三种方式
  21.     for (elem <- array1) println(elem)
  22.     // 第四种方式
  23.     array1.foreach(println)
  24.     // 第五种方式
  25.     val iter = array1.iterator
  26.     while (iter.hasNext)
  27.       println(iter.next())
复制代码
 update 方法

当对带有括号并包括一到多少参数的对象举行赋值时,编译器将使用对象的 update 方法对括号里的参数和等号右边的对象实验调用
  1. object Third {
  2.   def main(args: Array[String]): Unit = {
  3.     val obj = new SomeClass
  4.     val result = (obj(1, "key1") = "Hello")
  5.     println(result)
  6.   }
  7. }
  8. class SomeClass {
  9.   def update(arg1: Int, arg2: String, arg3: String): String = {
  10.     println("update method called")
  11.     arg1 + "|" + arg2 + "|" + arg3
  12.   }
  13. }
复制代码
实验结果
  1. update method called
  2. 1|key1|Hello
复制代码
在应用 update 时,等号右边的值会作为 update 方法的最后一个参数。因此,我们可以看到,update方法被默认调用,这个也是scala这门语言的便捷之处,每每通过隐式的方法,实际上调用简直实背后真的方法

可变数组ArrayBuffer

ArrayBuffer混入了mutable下Seq的两个子trait:IndexedSeq、Buffer,与Array一样,元素有先后之分,可以重复,可以随机访问,但是插入的服从不高。
  1.     val arr = new mutable.ArrayBuffer[Int]()
  2.     arr.append(1) //等价于+=,但可添加多个
  3.     // :+不会在arr1 上添加元素,而是新生成一个ArrayBuffer
  4.     val newArr1 = arr :+ 2
  5.     println(arr == newArr1) //false
  6.     val newArr2 = arr += 3 //元素加在数组最后面
  7.     println(arr == newArr2) //true
  8.     newArr2 += 4
  9.     println(arr) //ArrayBuff(1, 3, 4),因为是引用类型,所以对于可变集合,不建议添加元素后赋值给一个新变量
  10.     5 +=: arr //元素5加在数组前面
  11.     println(arr)  // ArrayBuffer(5, 1, 3, 4)
  12.     arr.prepend(6) //等价于+=:,但可添加多个
  13.     println(arr)  // ArrayBuffer(6, 5, 1, 3, 4)
  14.     arr.insert(1, 13, 59) //在指定的位置开始添加
  15.     println(arr)    // ArrayBuffer(6, 13, 59, 5, 1, 3, 4)  在索引1的位置添加13 59
  16.     arr.insertAll(2, newArr1)  // newArr1 ArrayBuffer(1, 2)
  17.     println(arr)   //  ArrayBuffer(6, 13, 1, 2, 59, 5, 1, 3, 4)
  18.     arr.prependAll(newArr2)  // newArr2 = arr  在前面添加
  19.     println(arr)   // ArrayBuffer(6, 13, 1, 2, 59, 5, 1, 3, 4, 6, 13, 1, 2, 59, 5, 1, 3, 4)
  20.     arr.remove(3, 10) // 删除指定的位置开始后10个元素 删除 [2, 59, 5, 1, 3, 4, 6, 13, 1, 2]
  21.     println(arr)   // ArrayBuffer(6, 13, 1, 59, 5, 1, 3, 4)
  22.     arr -= 13 //删除数组中的元素,如果存在则删除,不存在不做操作
  23.     println(arr)  // ArrayBuffer(6, 1, 59, 5, 1, 3, 4)  删除13
  24.     val newArr = arr.toArray
  25.     val buff = newArr.toBuffer
  26.     arr.foreach(println)   // arr 的遍历
  27.     // 创建二维数组
  28.     val array: Array[Array[Int]] = Array.ofDim[Int](2, 3) //两行三列
  29.     array.foreach(_.foreach(println))
复制代码
IndexedSeq

这种范例的紧张访问方式是通过索引,默认的实现方式为Vector

备注:这里的IndexedSeq是immutable包下的,相关联的还有Array和String

  1.     val x = IndexedSeq(1, 2, 3)
  2.     println(x.getClass)
  3.     println(x(0))
  4.     val y = Range(1, 5)
  5.     println(y)
复制代码
实验结果
  1. class scala.collection.immutable.Vector
  2. 1
  3. Range 1 until 5
复制代码
LinearSeq

紧张的区别在于其被分为头与尾两部分。其中,头是容器内的第一个元素,尾是除了头元素以外剩余的其他所有元素。LinearSeq默认的实现是List,是不可变列表
  1.     val x = collection.immutable.LinearSeq("a", "b", "c")
  2.     println(x.head)
  3.     println(x.tail)
复制代码
实验结果
  1. a
  2. List(b, c)
复制代码
List

  1.     // 1. 创建一个List
  2.     val list1 = List(23, 65, 87)
  3.     // 2. 访问和遍历元素
  4.     println(list1(1))
  5.     //    list1(1) = 12  //immutable包下的List没有update方法,即不能更改列表中的数据
  6.     list1.foreach(println)
  7.     // 3. 添加元素
  8.     val list2 = 10 +: list1
  9.     val list3 = list1 :+ 23
  10.     // 写成方法调用就是添加在前面,写成操作符的形式就添加在后面
  11.     val list4 = list2.::(51) //生成一个新的List,然后会把元素添加到list2开头,等价51 :: list2
  12.     println(list4)
  13.     val list5 = Nil.::(13)
  14.     println(list5)
  15.     val list7 = 17 :: 28 :: 59 :: 16 :: Nil // 常见创建列表的方法
  16.     println(list7)
  17.     // 4. 合并列表
  18.     val list9 = list5 ::: list7 // 等价于list7.:::(list5)
  19.     println(list9)
  20.     val list10 = list5 ++ list7 // 源码可以发现就是调用:::
  21.     println(list10)
复制代码
ListBuff

 相比于List,ListBuffer是可变的集合,可以添加,删除元素,属于scala.collection.mutable包下
  1.     // 1. 创建可变列表
  2.     val list1: ListBuffer[Int] = new ListBuffer[Int]()   // 不推荐
  3.     val list2 = ListBuffer(12, 53, 75) //scala中推荐使用的构建方法,使用伴生对象的方式
  4.     // 2. 添加元素
  5.     list1.append(15, 62)  // 后插
  6.     println(list1) // ListBuffer(15, 62)
  7.     list2.prepend(20)   // 前插
  8.     println(list2) // ListBuffer(20, 12, 53, 75)
  9.     list1.insert(1, 19, 22)   // 在索引1的位置添加19 22
  10.     println(list1) // ListBuffer(15, 19, 22, 62)
  11.     31 +=: 96 +=: list1 += 25 += 11   // 在lst1的前面添加元素31  96 在后面插入元素25 11
  12.     println(list1) // ListBuffer(31, 96, 15, 19, 22, 62, 25, 11)
  13.     // 3. 合并list
  14.     val list3 = list1 ++ list2 // 返回新的对象,list1和list2不变
  15.     println(list3) // ListBuffer(31, 96, 15, 19, 22, 62, 25, 11,  20, 12, 53, 75)
  16.     list1 ++= list2 // 在list1后添加list2的元素,list2不变,如果反过来就是list1 ++=: list2
  17.     println(list1)   // ListBuffer(31, 96, 15, 19, 22, 62, 25, 11, 20, 12, 53, 75)
  18.     println(list2)  // ListBuffer(20, 12, 53, 75)
  19.     // 4. 修改元素
  20.     list2(3) = 30 // 等价于 list2.update(3, 30)
  21.     // 5. 删除元素
  22.     list2.remove(2)
  23.     list2 -= 25
复制代码
Set

与其他任何一种编程语言一样,Scala中的Set集合类具有如下特点: 

i、不存在有重复的元素。 

ii、集合中的元素是无序的。换句话说,不能以索引的方式访问集合中的元素。 

iii、判断某一个元素是否在Set集合中比Seq范例的集合要快。

不可变的HashSet

  1.     val x = immutable.HashSet[String]("a", "c", "b")
  2.     //x.add("d")无法使用,因为是不可变集合,没有add方法。没有类似+=这样的操作
  3.     val y = x + "d" + "f" // 增加新的元素,生成一个新的集合
  4.     val z = y - "a" // 删除一个元素,生成一个新的集合
  5.     val a = Set(1, 2, 3)
  6.     val b = Set(1, 4, 5)
  7.     val c = a ++ b //合并集合
  8.     val d = a -- b // a中剔除b中的元素
  9.     val e = a & b // 与操作,交集
  10.     val f = a | b // 或操作,并集
复制代码
可变的HashSet

  1.     val x = new mutable.HashSet[String]()
  2.     x += "a" // 添加一个新的元素。注意此时没有生成一个新的集合
  3.     x.add("d") //因为是可变集合,所以有add方法,返回值是boolean类型
  4.     x ++= Set("b", "c") // 添加一个新的集合,改变的是x,参照listBuffer
  5.     x.foreach(each => println(each))
  6.     x -= "b" // 删除一个元素,remove返回值也是boolean类型
  7.     val flag = x.contains("a") // 是否包含元素
  8.     println(flag)
复制代码
不可变Map

Map这种数据布局是日常开发中使用非常频繁的一种数据布局。Map作为一个存储键值对的容器(key-value),其中key值必须是唯一的。 默认情况下,可以通过Map直接创建一个不可变的Map容器对象,这时候容器中的内容是不能改变的,在scala中,可以使用java相同的方式即(key,value)来标识键值对
  1.     // 两种创建map的方式
  2.     val peoples = Map("john" -> 19, "Tracy" -> 18, "Lily" -> 20) //不可变
  3.     val peopless = Map(("john", 19), ("Tracy", 18), ("Lily", 20))
  4.     // people.put("lucy",15) 会出错,因为是不可变集合。
  5.     //遍历方式1
  6.     for (p <- peoples) {
  7.       print(p + "  ") // (john,19)  (Tracy,18)  (Lily,20)
  8.     }
  9.     //遍历方式2
  10.     peoples.foreach(x => {
  11.       val (k, v) = x; print(k + ":" + v + "  ")
  12.     }) //john:19  Tracy:18  Lily:20
  13.     //遍历方式3
  14.     peoples.foreach({ case (k, v) => print(s"key: $k, value: $v  ") })
  15.     //遍历方式4
  16.     for (key <- peoples.keys) {
  17.       println(s"$key ---> ${peoples.get(key)}") //scala中的map.get返回的是一个Optional类型
  18.     }
  19.     println(peoples("Lily")) //等价于get
复制代码
可变的HashMap

  1.     val map = new mutable.HashMap[String, Int]()
  2.     map.put("john", 19) // 因为是可变集合,所以可以put
  3.     map += (("Tracy", 18))  // 增加,等价于put
  4.     map -= "john" // remove
  5.     map.contains("Lily") //false
  6.     map.foreach({ case (k, v) => println(s"key: $k, value: $v  ") })
复制代码
元组(元素组合)

元组也是可以理解为一个容器,可以存放各种相同或不同范例的数据。说的简单点,就是将多个无关的数据封装为一个团体,称为元组。Map 中的键值对其实就是元组,只不外元组的元素个数为 2,称之为对偶,二元元组

留意:元组中最大只能有 22 个元素。
  1.     // 1. 创建元组
  2.     val tuple: (String, Int, Char, Boolean) = ("hello", 100, 'a', true)
  3.     println(tuple)   // (hello,100,a,true)
  4.     // 2. 访问数据方式一
  5.     println(tuple._1)
  6.     println(tuple._2)
  7.     println(tuple._3)
  8.     println(tuple._4)
  9.     // 2. 访问数据方式二
  10.     println(tuple.productElement(0)) // 等价于_1,下标从零开始。
  11.     println(tuple.productElement(1)) // 等价于_2,下标从零开始。
  12.     println(tuple.productElement(2)) // 等价于_3,下标从零开始。
  13.     println(tuple.productElement(3)) // 等价于_4,下标从零开始。
  14.     // 3. 遍历元组数据
  15.     for (elem <- tuple.productIterator)
  16.       println(elem)
  17.     // 4. 嵌套元组
  18.     val mulTuple = (12, 0.3, "hello", (23, "scala"), 29)
  19.     println(mulTuple._4._2)   // scala
  20.     // 对偶
  21.     val map = Map("a" -> 1, "b" -> 2, "c" -> 3)
  22.     map.foreach(tuple => {
  23.       println(tuple._1 + "=" + tuple._2)
  24.     })
复制代码
队列

Scala 也提供了队列(Queue)的数据布局,队列的特点就是先辈先出。进队和出队的方法分别为 enqueue 和 dequeue
  1.     val que = new mutable.Queue[String]()
  2.     que.enqueue("a", "b", "c")
  3.     println(que.dequeue())   //a
  4.     println(que.dequeue())   //b
  5.     println(que.dequeue())   //c
复制代码
集合常用函数

根本属性和常用操纵

  1. val list: List[Int] = List(1, 2, 3, 4, 5, 6, 7)
  2. //获取集合长度
  3. println(list.length)
  4. //获取集合大小
  5. //有些集合(比如Set)可能没有length方法,在LinearSeq中等同于 length
  6.     val x = collection.immutable.LinearSeq("a", "b", "c")
  7.     println(x.size)
  8. //循环遍历
  9. list.foreach(println)
  10. //迭代器
  11. for (elem <- list.iterator) {
  12. println(elem)
  13. }
  14. //生成字符串
  15. println(list.mkString(","))
  16. //是否包含
  17. println(list.contains(3))
复制代码
衍生集合函数

  1.     val list1: List[Int] = List(1, 2, 3, 4, 5, 6, 7)
  2.     val list2: List[Int] = List(4, 5, 6, 7, 8, 9, 10)
  3.     //(1)获取集合的头
  4.     println(list1.head)
  5.     //(2)获取集合的尾(不是头的就是尾)
  6.     println(list1.tail)
  7.     //(3)集合最后一个数据
  8.     println(list1.last)
  9.     //(4)集合初始数据(不包含最后一个)
  10.     println(list1.init)
  11.     //(5)反转
  12.     println(list1.reverse)
  13.     //(6)取前(后)n 个元素
  14.     println(list1.take(3))
  15.     println(list1.takeRight(3))
  16.     //(7)去掉前(后)n 个元素
  17.     println(list1.drop(3))
  18.     println(list1.dropRight(3))
  19.     //(8)并集
  20.     println(list1.union(list2)) // 等价于:++
  21.     //(9)交集
  22.     println(list1.intersect(list2))
  23.     //(10)差集
  24.     println(list1.diff(list2))
  25.     //(11)拉链操作:如果两个集合的元素个数不相等,那么会将同等数量的数据进行拉链,多余的数据省略不用,返回一个List,其组成元素是二元组
  26.     println(list1.zip(list2))
  27.     //(12)滑窗
  28.     list1.sliding(3, 3).foreach(println)  // 返回值类型:Iterator[List[Int]]
  29.     // sliding的第一个参数定义窗口的长度,第二个参数定义滑动的步长,当窗口长度和步长相等时称为滚动,如果窗口长度小于步长将造成数据丢失
复制代码
集合盘算简单函数

  1.     val list: List[Int] = List(1, 5, -3, 4, 2, -7, 6)
  2.     val map = Map(("john", 19), ("Tracy", 18), ("Lily", 20))
  3.     //(1)求和
  4.     println(list.sum)
  5.     //(2)求乘积
  6.     println(list.product)
  7.     //(3)最大值
  8.     println(list.max)
  9.     //以后看到actionBy名字的方法,同时通过某种自定义函数的结果去执行action方法。
  10.     println(map.maxBy(_._2)) //("Lily", 20)
  11.     //(4)最小值
  12.     println(list.min)
  13.     println(map.minBy(_._2)) //("Tracy", 18)
  14.     //(5)排序
  15.     // (5.1)按照元素大小排序
  16.     println(list.sortBy(x => x))
  17.     println(list.sorted.reverse) //倒序,list里的reverse
  18.     println(list.sorted(Ordering[Int].reverse)) //倒序,Ordering里的reverse
  19.     // (5.2)按照元素的绝对值大小排序
  20.     println(list.sortBy(x => x.abs))
  21.     // (5.3)按元素大小升序排序
  22.     println(list.sortWith((x, y) => x < y))
  23.     // (5.4)按元素大小降序排序
  24.     println(list.sortWith((x, y) => x > y))
复制代码
备注:

(1)sorted:对一个集合举行自然排序,可以通报隐式的 Ordering

(2)sortBy:通过指定的属性举行排序,通过它的范例。可以通报隐式的 Ordering

def sortBy[B](f: A => B)(implicit ord: Ordering[B]): Repr = sorted(ord on f)

(3)sortWith:基于函数的排序,通过一个 comparator 函数,实现自界说排序的逻辑。

def sortWith(lt: (A, A) => Boolean): Repr = sorted(Ordering fromLessThan lt)

集合盘算高级函数

  1.     val list: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
  2.     val nestedList: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9))
  3.     val wordList: List[String] = List("hello world", "hello spark", "hello scala")
  4.     //(1)过滤
  5.     println(list.filter(x => x % 2 == 0)) // list.filter(_ % 2 == 0)
  6.     //(2)转化/映射
  7.     println(list.map(x => x + 1)) // list.map(_ + 1)
  8.     //(3)扁平化  将嵌套list 展开成一个list
  9.     println(nestedList.flatten) //List(1, 2, 3, 4, 5, 6, 7, 8, 9)
  10.     //(4)扁平化+映射 注:flatMap 相当于先进行 map 操作,在进行 flatten操作,集合中的每个元素的子元素映射到某个函数并返回新集合
  11.     println(wordList.flatMap(x => x.split(" "))) // List(hello, world, hello, spark, hello, scala)
  12.     //(5)分组:按照指定的规则对集合的元素进行分组
  13.     println(list.groupBy(x => x % 2)) //Map(1 -> List(1, 3, 5, 7, 9), 0 -> List(2, 4, 6, 8))
  14.     // Map(奇数 -> List(1, 3, 5, 7, 9), 偶数 -> List(2, 4, 6, 8))
  15.     println(list.groupBy(data => if (data % 2 == 0) "偶数" else "奇数"))
  16.     //(6)Reduce 简化(归约) :通过指定的逻辑将集合中的数据进行聚合,从而减少数据,最终获取结果。
  17.     // 将数据两两结合,实现运算规则
  18.     val ii: Int = list.reduce((x, y) => x - y) //list.reduce(_ - _ )
  19.     println("ii = " + ii)
  20.     // 从源码的角度,reduce 底层调用的其实就是 reduceLeft
  21.     // 1-2=-1  -1-3=-4 -4-4=-8.....
  22.     val i1 = list.reduceLeft((x, y) => x - y)
  23.     println(i1)
  24.     // 9-8=1 1-7=-6 -6-6=-12....
  25.     val i2 = list.reduceRight((x, y) => x - y)
  26.     println(i2)
  27.     //(7)Fold 折叠:化简的一种特殊情况。
  28.     // fold 方法使用了函数柯里化,存在两个参数列表,第一个参数列表为 : 零值(初始值),第二个参数列表为: 简化规则。fold 底层其实为 foldLeft
  29.     val i = list.foldLeft(1)((x, y) => x - y)
  30.     val i3 = list.foldRight(10)((x, y) => x - y)
  31.     // 两个 Map 的数据合并
  32.     val map1 = mutable.Map("a" -> 1, "b" -> 2, "c" -> 3)
  33.     val map2 = mutable.Map("a" -> 4, "b" -> 5, "d" -> 6)
  34.     val map3: mutable.Map[String, Int] = map2.foldLeft(map1) {
  35.       (map, kv) => {
  36.         val k = kv._1
  37.         val v = kv._2
  38.         map(k) = map.getOrElse(k, 0) + v
  39.         map
  40.       }
  41.     }
  42.     println(map3) // Map(b -> 7, d -> 6, a -> 5, c -> 3)
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

张裕

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表