详解 Scala 的集合类型

一、集合简介

1. 类型

  • 序列 Seq:类似于 Java 中的 List 接口
  • 集 Set:类似于 Java 中的 Set 接口
  • 映射 Map:类似于 Java 中的 Map 接口
  • 所有的集合都扩展自 Iterable 特质

2. 不可变集合

位于 scala.collection.immutable 包,指该集合对象不可修改,每次修改就会返回一个新对象,而不会对原对象进行修改。类似于 Java 中的 String 对象
在这里插入图片描述

  • Scala 中的 Array 和 String 类本质是使用 type 关键字为 Java 中对应类所设置的别名
  • Array 和 String 类本身并没有 extends IndexedSeq,Array 和 String 类使用时实际是被隐式转换成了 WrappedArray 和 WrappedString 类,而 WrappedArray 和 WrappedString 类继承了 IndexedSeq 特质
  • IndexedSeq 和 LinearSeq 的区别:
    • IndexedSeq 是通过索引来查找和定位,所以查询速度快,比如 String 就是一个索引集
    • LinearSeq 是线型的,即有头尾的概念,所以增删效率高,一般是通过遍历来查找,查询效率低

3. 可变集合

位于 scala.collection.mutable 包,指该集合对象可以直接对原对象进行修改,而不会返回新的对象。类似于 Java 中 StringBuilder 对象
在这里插入图片描述

  • 在操作不可变集合的时建议使用符号类方法
  • 在操作可变集合的时建议使用名称类方法

二、Seq 集合之数组

1. 不可变数组

1.1 创建
object TestImmutableArray {def main(args: Array[String]): Unit = {// 方式一/*Array[Int] 表示存储元素类型为 Int 的数组(10) 表示数组最大元素个数为 10*/val arr1: Array[Int] = new Array[Int](10)// 方式二/*Array() 本质是调用伴生对象的 apply() 方法*/val arr2: Array[Int] = Array(10, 20, 30, 40)}
}
1.2 操作
object TestImmutableArray {def main(args: Array[String]): Unit = {// 创建数组val arr: Array[Int] = Array(10, 20, 30, 40)// 1. 访问某个元素val i: Int = arr(0) // 底层是 Array 类的存根方法 apply(i: Int)println(i)// 2. 修改某个元素值(不可变数组是对象地址和容量不能改变,元素值可以修改)println(arr(1))arr(1) = 50 // 底层是 Array 类的存根方法 update(i: Int, value: T)println(arr(1))// 3. 遍历数组// 3.1 普通 for 循环 + 索引for(i <- 0 util arr.length) println(arr(i))for(i <- arr.indices) println(arr(i))// 3.2 普通 for 循环 + 元素,类似 Java 的增强 for 循环for(elem <- arr) println(elem)// 3.3 迭代器val iterator = arr.iterator()while(iterator.hasNext) println(iterator.next)// 3.4 foreach 方法:foreach(func: a => b)arr.foreach(println)// 3.5 所有元素整体以字符串打印println(arr.mkString(","))// 4. 添加元素(得到新数组)/*:+() 方法底层是先获取原数组的长度,再创建一个大小为原数组长度+1的新数组,将原数组的元素 copy 到新数组,最后将添加的值赋值给最后一个元素+:() 方法是向前添加元素*/val newArr1 = arr.:+(20)val newArr2 = newArr1.+:(8)println(arr.mkString("-")) // arr 没有改变println(newArr1.mkString("-"))println(newArr2.mkString("-"))// 简写val newArr3 = arr :+ 20val newArr4 = 8 +: arrprintln(arr.mkString("-"))println(newArr3.mkString("-"))println(newArr4.mkString("-"))val newArr5 = 2 +: 6 +: arr :+ 50 :+ 60println(newArr5.mkString("-"))}
}

2. 可变数组

ArrayBuffer 类

2.1 创建
object TestMutableArray {def main(args: Array[String]): Unit = {// 方式一/*ArrayBuffer[Int] 表示元素类型为 Int 的可变数组,[Int] 可以省略,元素类型为 Any() 可以不指定元素最大个数,调用的是辅助构造器,默认大小为 16*/// 需要导包import scala.collection.mutable.ArrayBufferval arr1: ArrayBuffer[Int] = new ArrayBuffer[Int]()// 方式二val arr2: ArrayBuffer[Int] = ArrayBuffer(10, 20, 30, 40)println(arr2) // ArrayBuffer(10, 20, 30, 40),调用 arr2.toString()}
}
2.2 操作
object TestMutableArray {def main(args: Array[String]): Unit = {// 创建数组val arr: ArrayBuffer[Int] = ArrayBuffer(10, 20, 30, 40)// 1. 访问元素println(arr(1))// 2. 修改元素值println(arr(0))arr(0) = 8println(arr(0))// 3. 遍历数组,同不可变数组遍历// 4. 添加元素// 4.1 符号类方法(不可变集合推荐)arr += 50 // 末尾追加println(arr)arr +=: 8 // 开头添加println(arr)// 4.2 名称类方法(可变集合推荐)arr.append(60, 70) // 末尾追加多个元素// arr.appendAll(ArrayBuffer(4, 5, 6))println(arr)arr.prepend(4, 6) // 开头添加多个元素// arr.prependAll(ArrayBuffer(4, 5, 6))println(arr)arr.insert(3, 11, 14) // 在指定下标位置添加多个元素println(arr)arr.insertAll(2, ArrayBuffer(4, 5, 6)) // 在指定下标位置添加一个数组println(arr)// 5. 删除元素arr.remove(1) // 删除下标为 1 的元素println(arr)arr.remove(3, 3) // 删除下标 3 及往后的 2 个元素println(arr)arr -= 40 // 删除元素 40,不存在无操作println(arr)}
}

3. 不可变与可变转换

object TestArrayTransform {def main(args: Array[String]): Unit = {// 1. 可变数组转不可变数组:toArrayval muArr: ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)val immuArr: Array[Int] = muArr.toArrayprintln(muArr)println(immuArr)// 2. 不可变数组转可变数组:toBufferval immuArr1: Array[Int] = Array(4, 5, 6)val muArr1: mutable.Buffer[Int] = immuArr1.toBufferprintln(immuArr1)println(muArr1)}
}

4. 多维数组

4.1 创建
object TestMultiArray {def main(args: Array[String]): Unit = {/*Array.ofDim[Int] 表示创建指定维度的元素类型为 Int 的数组(2, 3) 表示数组维度为 2 行 3 列,即该多维数组有 2 个数组元素,每个数组元素有 3 个元素*/val mulArray: Array[Array[Int]] = Array.ofDim[Int](2, 3)}
}
4.2 操作
object TestMultiArray {def main(args: Array[String]): Unit = {// 创建多维数组val mulArray: Array[Array[Int]] = Array.ofDim[Int](2, 3)// 1. 访问元素println(mulArray(0)(1))// 2. 修改元素值mulArray(1)(2) = 10mulArray(0)(0) = 30// 3. 遍历多维数组for(i <- mulArray.indices; j <- mulArray(i).indices) {if(j == mulArray(i).length -1) println() else println(mulArray(i)(j) + "\t")}mulArray.foreach(_.foreach(println))}
}

三、Seq 集合之List

1. 不可变 List

1.1 创建
object TestList {def main(agrs: Array[String]): Unit = {// 1. 使用伴生对象的 apply 方法(由于 List 是 sealed abstract class,不能使用 new)// sealed class 密封类,与这个类所有相关的对象和子类必须都定义在同一个源文件.scala 中val list1: List = List(10, 20, 30)// 2. 使用空集合、:: 方法 和 :: 类创建// Nil 是继承 List 的一个 case object// :: 方法 是 List 类中的一个方法,实现是创建并返回一个 :: 类// :: 类,是继承 List 的一个 case classval list2 = 10 :: 20 :: 30 :: Nil  }
}
1.2 操作
object TestList {def main(agrs: Array[String]): Unit = {// 创建 Listval list1: List = List(10, 20, 30)// 1. 访问和遍历元素println(list1(1)) // 虽然 LinearSeq 没有索引,但为了方便操作底层做了优化list1.foreach(println)// list(1) = 13 // error,不能使用索引方式修改// 2. 添加元素// 2.1 使用 +: 和 :+val list2 = list1 :+ 40 // 尾部添加println(list2)val list3 = 8 +: list1 // 头部添加println(list3)// 2.2 使用 :: 方法头部添加val list4 = 4 :: 6 :: 8 :: list1 println(list4)// 3. 合并列表,也称为扁平化// 3.1 使用 ::: 方法val list5 = list2 ::: list3 // list3.:::(list2)println(list5)// 3.2 使用 ++ 方法,内部也是调用 ::: 方法val list6 = list2 ++ list3 println(list6)}
}

2. 可变 ListBuffer

2.1 创建
object TestListBuffer {def main(args: Array[String]): Unit = {// 1. 使用 new 创建val list1: ListBuffer[Int] = new ListBuffer[Int]()// 2. 使用伴生对象的 apply 方法val list2 = ListBuffer(10, 20, 30)}
}
2.2 操作
object TestListBuffer {def main(args: Array[String]): Unit = {// 创建val list1 = ListBuffer(10, 20, 30)// 1. 访问元素println(list1(0))// 2. 修改元素print(list1(1))list1(1) = 22 // 底层是调用 list1.update(1, 22) 方法print(list1(1))// 3. 添加元素// 3.1 使用 += 和 +=:list1 += 40 += 50println(list1)6 +=: 8 +=: list1 += 60println(list1)// 3.2 使用 append/appendAll/prepend/prependAll/insert/insertAlllist1.append(66, 68)println(list1)list1.prepend(2, 4)println(list1)list1.insert(1, 3, 4)println(list1)// 4. 合并列表// 4.1 使用 ++ (返回新列表,操作的列表不改变)val list2 = ListBuffer(2, 3, 4)println(list1)println(list2)println("================")val list3 = list1 ++ list2println(list1)println(list2)println(list3)// 4.2 使用 ++=/++=: (调用方法的列表改变,参数列表不改变)val list4 = ListBuffer(2, 3, 4)println(list1)println(list4)println("================")list1 ++= list4println(list1)println(list4)// 5. 删除元素list1.remove(2) // 删除索引 2 位置元素println(list1)list1 -= 10 // 删除值为 10 的元素println(list1)}
}

四、Set 集合

1. 不可变 Set

1.1 创建
object TestImmutableSet {def main(args: Array[String]): Unit = {// 使用伴生对象 apply 方法创建(Set 是 trait,不能使用 new)val set1 = Set(11, 11, 12, 13, 14, 14, 15) // 无序无重复println(set1) // 去除重复值}
}
1.2 操作
object TestImmutableSet {def main(args: Array[String]): Unit = {// 创建val set1 = Set(11, 11, 12, 13, 14, 14, 15)// 1. 添加元素val set2 = set1 + 10 // set1.+(10)println(set1) // set1 不改变println(set2)// 2. 合并集合val set3 = Set(6, 11, 12, 13, 8, 4)val set4 = set1 ++ set3println(set1)println(set3)println(set4)// 3. 删除元素val set5 = set3 - 4 // set3.-(4)println(set3)println(set5)// 4. 遍历set1.foreach(println)for(elem <- set1) println(elem)}
}

2. 可变 mutable.Set

2.1 创建
object TestMutableSet {def main(args: Array[String]): Unit = {// 导入可变集合包import scala.collection.mutable// 使用伴生对象创建val set1: mutable.Set[Int] = mutable.Set(11, 11, 12, 13, 14, 14, 15)println(set1)}
}
2.2 操作
import scala.collection.mutable
object TestMutableSet {def main(args: Array[String]): Unit = {// 创建val set1: mutable.Set[Int] = mutable.Set(11, 11, 12, 13, 14, 14, 15)// 1. 添加元素// 1.1 使用 +=set1 += 10println(set1)// 1.2 使用 add,底层调用 +=,返回值为 boolean,!set.contains(elem)val res1 = set1.add(10)  // falseprintln(set1)val res2 = set1.add(8)  // trueprintln(set1)// 2. 删除元素// 1.1 使用 -=set1 -= 10println(set1)// 1.2 使用 remove,底层调用 -=,返回值为 boolean,set.contains(elem)val res1 = set1.remove(10)  // falseprintln(set1)val res2 = set1.remove(8)  // trueprintln(set1)// 3. 合并集合val set2 = mutable.Set(2, 2, 3, 4, 4, 5)println(set1)println(set2)set1 ++= set2 // 调用者发生改变println(set1)println(set2) // 不改变}
}

五、Map 集合

Scala 中的 Map 和 Java 类似, 也是一个散列表,它存储的内容也是键值对(key-value)映射,可以转化成二元组的集合

1. 不可变 Map

1.1 创建
object TestImmutableMap {def main(args: Array[String]): Unit = {// Map 是一个 trait,使用伴生对象的 apply 方法val map1: Map[String, Int] = Map("a" -> 10, "b" -> 20, "hello" -> 30)println(map1)println(map1.getClass)}
}
1.2 操作
object TestImmutableMap {def main(args: Array[String]): Unit = {// 创建val map1: Map[String, Int] = Map("a" -> 10, "b" -> 20, "hello" -> 30)// 1. 访问 key 对应的值// 1.1 使用 get()// Option 是一个密封抽象类,其子类有 Some 和 Noneval value1: Option = map1.get("a") // Some(10)println(value1.get)val value2: Option = map1.get("c") // None// println(value2.get) // error// 1.2 使用 getOrElse()val value3 = map1.getOrElse("c", 0) // 如果 key 不存在,就返回默认值 0// 1.3 使用 map(key)println(map1("a")) // 存在即获取值,不存在则抛异常,底层实现是 get() 加模式匹配// 2. 遍历Map// 2.1 foreachmap1.foreach(println) // 打印 KV 元组map1.foreach( kv: (String, Int) => println(kv) ) // 等价于foreach(println)// 2.2 for 循环for(key <- map1.keys) {println(s"$key -> ${map1.get(key).get}")}}
}

2. 可变 mutable.Map

2.1 创建
object TestMutableMap {def main(args: Array[String]): Unit = {// 导入可变集合的包import scala.collection.mutable// 使用伴生对象的 apply 方法创建val map1: mutable.Map[String, Int] = mutable.Map("a" -> 10, "b" -> 20, "hello" -> 30)println(map1)println(map1.getClass) // HashMap}
}
2.2 操作
import scala.collection.mutable
object TestMutableMap {def main(args: Array[String]): Unit = {// 创建val map1 = mutable.Map("a" -> 10, "b" -> 20, "hello" -> 30)// 1. 访问 key 对应的值// 1.1 使用 get()// Option 是一个密封抽象类,其子类有 Some 和 Noneval value1: Option = map1.get("a") // Some(10)println(value1.get)val value2: Option = map1.get("c") // None// println(value2.get) // error// 1.2 使用 getOrElse()val value3 = map1.getOrElse("c", 0) // 如果 key 不存在,就返回默认值 0// 1.3 使用 map(key)println(map1("a")) // 存在即获取值,不存在则抛异常,底层实现是 get() 加模式匹配// 2. 添加元素// 2.1 使用 +=map1 += (("c", 7))println(map1)// 2.2 使用 putmap1.put("d", 16) // 底层调用的 update(k, v), update 底层调用 +=println(map1)// 3. 删除元素// 3.1 使用 -=map1 -= "c"println(map1)// 3.2 使用 removemap1.remove("d") // 底层调用的 -=println(map1)// 4. 修改元素map1.update("c", 7) // key 不存在则相当于 putprintln(map1)map1.update("a", 8) // key 存在则修改值println(map1)// 5. 合并mapval map2 = Map("aaa" -> 10, "b" -> 28, "hello" -> 40)map1 ++= map2println(map1) // 将 map2 中的元素覆盖或添加到 map1println(map2) // map2 不改变val map3: Map[String, Int] = map2 ++ map1println(map3)}
}

六、元组

元组可以理解为一个容器,可以存放各种相同或不同类型的数据,即将多个无关的数据封装为一个整体,称为元组

1. 创建

object TestTuple {def main(args: Array[String]): Unit = {// 元组中最大只能有 22 个元素(Tuple1~22)val tuple: (String, Int, Char, Boolean) = ("hello", 10, 'a', true)println(tuple)}
}

2. 操作

object TestTuple {def main(args: Array[String]): Unit = {// 创建val tuple: (String, Int, Char, Boolean) = ("hello", 10, 'a', true)// 1. 访问元素// 1.1 使用 _n println(tuple._1) // 四个元素分别为 _1, _2, _3, _4// 1.2 使用 productElement(index)println(tuple.productElement(0)) // 索引从 0 开始// 2. 遍历元组for(elem <- tuple.productIterator) {println(elem)}// 3. Map 与元组的关系/*Map 的每一个键值对是一个二元组(Tuple2),也称为对偶元组*/val map1 = Map("a" -> 10, "b" -> 20, "c" -> 30)// 等价于val map2 = Map(("a", 10), ("b", 20), ("c", 30))// 4. 嵌套元组val mulTuple = ("hello", 100, 'a', (0.3, "scala"), true)println(mulTuple._4._2)}
}

七、集合常用函数

1. 基本属性和操作

object TestCollectionFunc {def main(args: Array[String]): Unit = {val list: List[Int] = List(1, 2, 3, 4, 5, 6, 7)//(1)获取集合长度println(list.length) // Set 和 Map 没有 length//(2)获取集合大小,等同于 lengthprintln(list.size)//(3)循环遍历list.foreach(println)//(4)迭代器for (elem <- list.iterator) {println(elem)}//(5)生成字符串println(list.mkString(","))//(6)是否包含println(list.contains(3))}
}

2. 衍生集合

object TestCollectionFunc {def main(args: Array[String]): Unit = {val list1: List[Int] = List(1, 2, 3, 4, 5, 6, 7)val list2: List[Int] = List(11, 2, 3, 44, 5, 66, 77, 88)//(1)获取集合的头 val res1: Int = list1.headprintln(res1)//(2)获取集合的尾(去除头元素后的集合)val res2: List[Int] = list1.tailprintln(res2)//(3)集合最后一个数据val res3: Int = list1.lastprintln(res3)//(4)集合初始数据(不包含最后一个)val res4: List[Int] = list1.initprintln(res4)//(5)反转val res5: List[Int] = list1.reverseprintln(res5)//(6)取前(后)n 个元素val res6: List[Int] = list1.take(3) // 取前 3 个println(res6)val res7: List[Int] = list1.takeRight(3) // 取后 3 个println(res7)//(7)去掉前(后)n 个元素val res8: List[Int] = list1.drop(3) // 去掉前 3 个println(res8)val res9: List[Int] = list1.dropRight(3) // 去掉后 3 个println(res9)//(8)并集(合并集合),Set 合并会去重,Map 合并会添加覆盖val union: List[Int] = list1.union(list2)println(union)println(list1 ::: list2)//(9)交集val intersection: List[Int] = list1.intersect(list2)println(intersection) // 两个集合的公共元素//(10)差集val diff1: List[Int] = list1.diff(list2) // 属于 list1 且不属于 list2 的元素println(diff1)val diff2: List[Int] = list2.diff(list1) // 属于 list2 且不属于 list1 的元素println(diff2)//(11)拉链(两个集合同位置的元素构成一个二元组形成的集合,落单部分丢弃)val zip1: List[(Int, Int)] = list1.zip(list2) // 元组中 list1 元素在前println(zip1)val zip2: List[(Int, Int)] = list2.zip(list1)println(zip2)//(12)滑窗(滑动开窗)val slide1: Iterator = list1.sliding(3) // 开窗大小为 3 个元素,每次滑动 1 个元素for(elem <- slide) {println(elem) // elem: List[Int]}// 滚动窗口val slide2: Iterator = list2.sliding(3, 3) // 开窗大小为3个元素,每次滑动3个元素}
}

3. 集合计算初级函数

object TestCollectionFunc {def main(args: Array[String]): Unit = {val list1: List[Int] = List(1, 5, -3, 4, 2, -7)val list2 = List(("a", 1), ("b", 5), ("c", -3), ("d", 4), ("e", 2), ("f",-7))//(1)求和val res1: Int = list1.sumprintln(res1)// 等价于val res2: Int = 0for(elem <- list1) res2 += elemprintln(res2)//(2)求乘积val res3: Int = list1.productprintln(res3)//(3)最大值val res4: Int = list1.maxprintln(res4)// maxBy 可以指定比较的元素val res5: Int = list2.maxBy( _._2 ) //((tuple:(String,Int)) => tuple._2)println(res5)//(4)最小值val res6: Int = list1.minprintln(res6)val res7: Int = list2.minBy( _._2 ) //((tuple:(String,Int)) => tuple._2)println(res7)//(5)排序(针对有序集合 List)// 5.1 使用 sortedval res8: List[Int] = list1.sorted // 默认升序,list1.sorted(Ordering[Int])println(res8)val res9 = list1.sorted(Ordering[Int].reverse) // 使用隐式参数指定降序println(res9)// 5.2 使用 sortBy 指定排序元素val ress = list2.sortBy(_) //元组排序,先比较第一个元素,相同则比较第二个元素,依次类推println(ress)val res10 = list2.sortBy(_._2) // 默认升序,list2.sortBy(_._2)(Ordering[Int])println(res10)val res11 = list2.sortBy(_._2)(Ordering[Int].reverse) // 降序println(res11)// 5.3 使用 sortWith 指定排序规则,类似于 Java 的 Comparatorval res12 = list1.sortWith( _ < _ ) // 升序,((a:Int, b:Int) => a < b) println(res12)}
}

4. 集合计算高级函数

4.1 过滤
object TestCollectionFunc {def main(args: Array[String]): Unit = {val list = List(1,2,3,4,5,6,7,8,9)/*过滤函数:filter(func: A => Boolean),true 保留*/// 选取偶数val evenList = list.filter(_ % 2 == 0) // ((a: Int) => a % 2 == 0)println(evenList)}
}
4.2 转化/映射
object TestCollectionFunc {def main(args: Array[String]): Unit = {val list = List(1,2,3,4,5,6,7,8,9)/*映射函数:map(func: A => B)*/// 所有元素乘以 2val resList1 = list.map(_ * 2)println(resList1)}
}
4.3 扁平化
object TestCollectionFunc {def main(args: Array[String]): Unit = {val nestedList: List[List[Int]] = List(List(1,2,3),List(4,5),List(6,7,8,9))/*扁平化函数:flatten(a: List[List[A]])*/val flatList = nestedList.flattenprintln(flatList)}
}
4.4 扁平化 + 映射
object TestCollectionFunc {def main(args: Array[String]): Unit = {// 针对一组字符串进行分词后以单词列表输出val words: List[String] = List("Hello world", "hello scala and java", "good job", "work hard")/*扁平化映射函数:flatMap(func: A => B)*/val flatMapList = words.flatMap(_.split(" ")) // 分词并扁平化println(flatMapList)// 等价于val splitWord: List[Array[String]] = words.map(_.split(" "))val flattenList = splitWord.flattenprintln(flattenList)}
}
4.5 分组
object TestCollectionFunc {def main(args: Array[String]): Unit = {val list = List(1,2,3,4,5,6,7,8,9)/*分组函数:groupBy(func: A => K),返回值为 Map[K, List[A]]*/// 按奇偶分组val groupMap1: Map[String, List[Int]] = list.groupBy(x => {if(x % 2 == 0) "偶数" else "奇数"})println(groupMap1)// 给定一组词汇,按单词的首字母分组val wordList: List[String] = List("alice", "bob", "canon", "curry", "bike")val groupMap2: Map[Char, List[String]] = wordList.groupBy( _.charAt(0) )}
}
4.6 简化(归约)
object TestCollectionFunc {def main(args: Array[String]): Unit = {val list = List(1,2,3,4)/*归约函数:reduce(op: (A1, A1) => A1): A1,底层是调用 reduceLeft()reduceLeft(op: (B, A) => B): B,聚合状态 B 可以和当前数据 A 类型不一致reduceRight(op: (A, B) => B): B,聚合状态 B 在右*/// 计算累加val res1: Int = list.reduce(_ + _) // (((1+2)+3)+4) = 10val res2: Int = list.reduceLeft(_ + _) // (((1+2)+3)+4) = 10val res3: Int = list.reduceRight(_ + _) // 1+(2+(3+4)) = 10// 计算累减val res4: Int = list.reduce(_ - _) // (((1-2)-3)-4) = -8val res5: Int = list.reduceLeft(_ - _) // (((1-2)-3)-4) = -8val res6: Int = list.reduceRight(_ - _) // 1-(2-(3-4)) = -2}
}
4.7 折叠
object TestCollectionFunc {def main(args: Array[String]): Unit = {val list = List(1,2,3,4)/*折叠函数:fold(z: A1)(op: (A1, A1) => A1): A1,底层调用foldLeft,z 是初始状态值foldLeft(z: B)(op: (B, A) => B): BfoldRight(z: B)(op: (A, B) => B): B,底层调用 reverse.foldLeft*/val result1: Int = list.fold(10)(_ + _) // 10 + 1 + 2 + 3 + 4 = 20val result2: Int = list.foldLeft(10)(_ - _) // 10 - 1 - 2 - 3 - 4 = 0val result3: Int = list.foldRight(11)(_ - _) // 1 - (2 - (3 - (4 - 11))) = 9}
}
4.8 应用案例
object TestMergeMap {def main(args: Array[String]): Unit = {// 合并 map:没有 key 则添加,有 key 则值相加val map1 = Map("a" -> 1, "b" -> 2, "c" -> 3)val map2 = mutable.Map("a" -> 4, "b" -> 5, "c" -> 6, "d" -> 8)val mergeMap = map1.foldLeft(map2)( (b: mutable.Map[String, Int], a: (String, Int)) => {val key = a._1val value = a._2b(key) = b.getOrElse(key, 0) + valueb})}
}

5. WordCount 案例

5.1 案例 1

单词计数:将集合中出现的相同的单词,进行计数,取计数排名前三的结果

object TestWordCount {def main(args: Array[String]): Unit = {// 原始字符串集合val strs: List[String] = List("Hello Scala Hbase Kafka", "Hello Scala Hbase", "Hello Scala", "Hello")// 分词并扁平化val words: List[String] = strs.flatMap(_.split(" "))// 分组val groupWords: Map[String, List[String]] = words.groupBy(w=>w) // 不能使用 _// 计数// (String, List) => (String, Int)val countMap: Map[String, Int] = groupWords.map(kv => (kv._1, kv._2.length))// 将 map 转化为 list 再降序取前 3val resultList: List[(String, Int)] = countMap.toList.sortWith(_._2 > _._2).take(3)println(resultList)}
}
5.2 案例 2

针对已经进行预统计的字符串集合,将集合中出现的相同的单词,进行计数,取计数排名前三的结果

object TestFlexWordCount {def main(args: Array[String]): Unit = {// 原始字符串集合val strs: List[(String, Int)] = List(("Hello Scala Hbase Kafka", 2), ("Hello Scala Hbase", 1), ("Hello Scala", 3), ("Hello", 4))// 分词val wordList: List[(String, Int)] = strs.flatMap(elem => { // 一进多出需扁平化for(a <- elem._1.split(" ")) yield (a, elem._2)})// 合并计数import scala.collection.mutablevar countMap: mutable.Map[String, Int] = mutable.Map()countMap = wordList.foldLeft(countMap)( (countMap, elem) => {val key = elem._1val value = elem._2countMap(key) = countMap.getOrElse(key, 0) + valuecountMap})// 将 Map 转化为 List 并降序取前 3val resultList: List[(String, Int)] = countMap.toList.sortWith(_._2 > _._2).take(3)println(resultList)}
}

八、队列

队列的特点就是先进先出。进队和出队的方法分别为 enqueue 和 dequeue

object TestQueue {def main(args: Array[String]): Unit = {// 创建可变队列import scala.collection.mutableval queue1 = new mutable.Queue[String]()val queue2 = mutable.Queue() // 伴生对象 apply 方法// 入队queue1.enqueue("a", "b", "c")println(queue1)// 出队println(queue1.dequeue())println(queue1)println(queue1.dequeue())println(queue1)println(queue1.dequeue())println(queue1)// 创建不可变队列import scala.collection.immutable// val queue = new immutable.Queue() // 密封类不能使用 new 创建val queue3 = Queue("a", "b", "c") // 伴生对象 apply 方法println(queue3)// 不可变队列的入队和出队操作会创建新的队列,自身不改变val queue4 = queue3.enqueue("d")println(queue3)println(queue4)}
}

九、并行集合

Scala 为了充分使用多核 CPU,提供了并行集合,用于多核环境的并行计算

object TestParallel {def main(args: Array[String]): Unit = {// 串行集合val result1: immutable.IndexedSeq[Long] = (1 to 100).map( a => {Thread.currentThread.getId})println(result1) // 都是一个线程,Vector// 并行集合val result2: ParSeq[Long] = (1 to 100).par.map( a => {Thread.currentThread.getId})println(result2) // 有多个线程处理,ParVector}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/841786.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ISSCC论文详解 2023 16.1 MulTCIM 存内计算在多模态领域的应用前沿论文

多模态模型&#xff0c;是指具备理解来自不同模态&#xff08;如视觉、自然语言、语音等&#xff09;的混合信号能力的神经网络模型&#xff0c;是当今人工智能模型发展的重要方向之一。本文将要介绍的文献题目为《16.1 MulTCIM: A 28nm 2.24μJ/Token Attention-Token-Bit Hyb…

一些常见的程序设计问题

秒杀 redis缓存库存 1.判断库存名额是否充足&#xff0c;2.进行扣减 为了防止超卖&#xff0c;必须保证这两部的原子性 库存扣减后发送mq消息&#xff0c;去异步执行创建订单流程&#xff0c;创建订单失败会造成少卖。可加重试机制&#xff0c;对多次重试依旧失败的&#xff…

[论文阅读笔记31]Mamba (Selective Structured State Space Model) 及其应用

最近想学一下Mamba模型&#xff0c;奈何看了很多视频还是感觉一知半解&#xff0c;因此做一篇笔记&#xff0c;顺便介绍一下Mamba结构作为CV backbone和时间序列预测领域的应用。 论文1. Mamba: Linear-Time Sequence Modeling with Selective State Spaces 0. Abstract 现有…

VLAN高级特性

1.VLAN聚合 &#xff08;1&#xff09;VLAN聚合产生的技术背景 &#xff08;2&#xff09;VLAN聚合概述 &#xff08;3&#xff09;VLAN聚合的原理 多个Sub-VLAN共享一个网关地址&#xff0c;节约了子网网络地址、子网定向广播地址、子网缺省网关地址&#xff0c;且各Sub-VLAN…

微信小程序--微信开发者工具使用小技巧(3)

一、微信开发者工具使用小技巧 1、快速创建小程序页面 在app.json中的pages配置项&#xff0c;把需要创建的页面填写上去 2、快捷键使用 进入方式 1&#xff1a; 文件–>首选项–> keyboard shortcuts 进入快捷键查看与设置 进入方式 2&#xff1a; 设置–>快捷键…

JVM学习-方法区(元空间)

运行时数据区结构图 从线程共享与否角度来看 栈、堆、方法区的交互关系 方法区 《Java虚拟机规范》中明确说明&#xff1a;“尽管所有的方法区在逻辑上属于堆的一部分&#xff0c;但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩”&#xff0c;但对于HotSpotJVM而…

布鲁可冲刺上市:极其依赖第三方,多个授权将到期,朱伟松突击“套现”

“奥特曼”概念股来了。 近日&#xff0c;布鲁可集团有限公司&#xff08;下称“布鲁可”&#xff09;递交招股书&#xff0c;准备在港交所主板上市&#xff0c;高盛和华泰国际为其联席保荐人。据贝多财经了解&#xff0c;布鲁可的经营主体为上海布鲁可科技集团有限公司。 天眼…

轻量级 C Logger

目录 一、描述 二、实现效果 三、使用案例 四、内存检测 一、描述 最近实现一个 WS 服务器&#xff0c;内部需要一个日志打印记录服务器程序的运行过程&#xff0c;故自己实现了一个轻量级的 logger&#xff0c;主要包含如下特征&#xff1a; 可输出 debug、info、warn、er…

历年高校招生计划数据 API 数据接口

历年高校招生计划数据 API 数据接口 基础数据 / 高校招生&#xff0c;各高校历年招生计划数据&#xff0c;高校招生数据 / 历年计划。 1. 产品功能 支持历年高校招生计划数据查询&#xff1b;包含各高校招生计划详细数据&#xff1b;多维度查询条件支持&#xff1b;毫秒级查询…

安全分析[2]之计算机系统安全分析

文章目录 计算机系统结构计算机系统安全风险软件安全漏洞 计算机系统结构 计算机系统安全风险 计算机硬件安全&#xff1a;因设计不当、器件的质量及使用寿命的限制、外界因素等导致的计算机系统硬件出现故障&#xff0c;进而影响到整个系统的安全。特别是如果是CPU出现安全漏…

【Go专家编程——协程】

1 协程的概念 1.1 基本概念 进程是应用程序的启动实例&#xff0c;每个进程都有独立的内存空间&#xff0c;不同进程通过进程间的通信方式来通信线程从属于进程&#xff0c;每个进程至少包含一个线程&#xff0c;线程是CPU调度的基本单元&#xff0c;多个线程之间可以共享进程…

PCIe总线-事物层之TLP请求和完成报文格式介绍(六)

1.概述 TLP报文按照类型&#xff0c;可以大致分为4中类型&#xff0c;分别是IO请求报文、存储器请求报文、配置请求报文、完成报文和消息请求报文。IO请求报文可分为IO读请求&#xff08;不携带数据&#xff09;和IO写请求&#xff08;携带数据&#xff09;。存储器请求报文可…

架构师系列-定时任务解决方案

定时任务概述 在很多应用中我们都是需要执行一些定时任务的&#xff0c;比如定时发送短信&#xff0c;定时统计数据&#xff0c;在实际使用中我们使用什么定时任务框架来实现我们的业务&#xff0c;定时任务使用中会遇到哪些坑&#xff0c;如何最大化的提高定时任务的性能。 我…

Spark-RDD-依赖关系详解

Spark概述 Spark-RDD概述 Spark-RDD-依赖关系 在Apache Spark中&#xff0c;RDD&#xff08;Resilient Distributed Dataset&#xff09;是一种基本的抽象数据结构&#xff0c;代表了分布式的、不可变的数据集。 RDD之间的依赖关系在Spark中非常重要&#xff0c;因为它们决定了…

DBAPI怎么进行数据格式转换

DBAPI如何进行数据格式的转换 假设现在有个API&#xff0c;根据学生id查询学生信息&#xff0c;访问API查看数据格式如下 {"data":[{"name":"Michale","phone_number":null,"id":77,"age":55}],"msg"…

【java程序设计期末复习】chapter1 java入门

java入门 java的特点 &#xff08;1&#xff09;简单 Java要比C简单&#xff0c;C中许多容易混淆的概念&#xff0c;或者被Java弃之不用了&#xff0c;或者以一种更清楚更容易理解的方式实现 &#xff08;2&#xff09;面向对象 Java是面向对象的编程语言 &#xff08;3&…

如何关闭或者减少屏蔽 CloudFlare 的真人检测

经常浏览境外网站的应该常碰到一个真人检测的提示(如下图所示)。最近,明月就收到了一个知乎上的付费咨询:问我如何去掉这个提示,由此明月也特别的研究了一下这个“真人检测”,这算是 CloudFlare 的一个特色了,基本上大家看到站点访问有这个提示的几乎都是用了 CloudFlar…

【同构字符串】python

思路&#xff1a; 先记录同一个值出现的次数&#xff0c;再将字典中的值取出&#xff0c;比较2个列表即可 代码&#xff1a; class Solution:def isIsomorphic(self, s: str, t: str) -> bool:dit1dict()dit2dict()for i in range(len(s)):if s[i] not in dit1:dit1[s[i…

01.并发编程简介

1 什么是并发编程 所谓并发编程是指在一台处理器上“同时”处理多个任务。并发是在同一实体上的多个事件。多个事件在同一时间间隔发生。 2 为什么我们要学习并发编程&#xff1f; 最直白的原因就是因为面试需要&#xff0c;大厂的 Java 岗的并发编程能力属于标配。 而在非大厂…

CentOS 7.9部署宝塔面板超详细

CentOS7 部署宝塔面板 Linux的宝塔面板搭建起来非常轻松&#xff0c;也可以用一句话来形容&#xff0c;如果喝水一样简单&#xff0c;只需一条命令剩下的交给时间&#xff0c;几分钟就能部署好&#xff0c;然后就可以直接进行登录&#xff0c;直接可以安装LNMP、LAMP平台&…