一、集合简介
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}
}