第 7 章 集合
7.1 集合简介
1)Scala 的集合有三大类:序列 Seq、集 Set、映射 Map,所有的集合都扩展自 Iterable
特质。
2)对于几乎所有的集合类,Scala 都同时提供了可变和不可变的版本,分别位于以下两
个包
不可变集合:scala.collection.immutable
可变集合: scala.collection.mutable
3)Scala 不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而
不会对原对象进行修改。类似于 java 中的 String 对象
4)可变集合,就是这个集合可以直接对原对象进行修改,而不会返回新的对象。类似
于 java 中 StringBuilder 对象
建议:在操作集合的时候,不可变用符号,可变用方法
7.1.1 不可变集合继承图
1)Set、Map 是 Java 中也有的集合
2)Seq 是 Java 没有的,我们发现 List 归属到 Seq 了,因此这里的 List 就和 Java 不是同一个
概念了
3)我们前面的 for 循环有一个 1 to 3,就是 IndexedSeq 下的 Range
4)String 也是属于 IndexedSeq
5)我们发现经典的数据结构比如 Queue 和 Stack 被归属到 LinearSeq(线性序列)
6)大家注意 Scala 中的 Map 体系有一个 SortedMap,说明 Scala 的 Map 可以支持排序
7)IndexedSeq 和 LinearSeq 的区别:
(1)IndexedSeq 是通过索引来查找和定位,因此速度快,比如 String 就是一个索引合,通过索引即可定位
(2)LinearSeq 是线型的,即有头尾的概念,这种数据结构一般是通过遍历来查找
7.1.2 可变集合继承图
7.2 数组
7.2.1 不可变数组
1)第一种方式定义数组
定义:val arr1 = new Array[Int] (10)
(1)new 是关键字
(2)[Int]是指定可以存放的数据类型,如果希望存放任意数据类型,则指定 Any
(3)(10),表示数组的大小,确定后就不可以变化
2)第二种方式定义数组
val arr1 = Array(1, 2)
(1)在定义数组时,直接赋初始值
(2)使用 apply 方法创建数组对象
3)案例实操
package chapter07
object Test01_ImmutableArray {
def main(args: Array[String]): Unit = {
// 1. 创建数组
val arr: Array[Int] = new Array[Int](5)
// 另一种创建方式
val arr2 = Array(12, 37, 42, 58, 97)
println(arr)
// 2. 访问元素
println(arr(0))
println(arr(1))
println(arr(4))
// println(arr(5))
arr(0) = 12
arr(4) = 57
println(arr(0))
println(arr(1))
println(arr(4))
println("========================")
// 3. 数组的遍历
// 1) 普通for循环
for (i <- 0 until arr.length) {
println(arr(i))
}
for (i <- arr.indices) println(arr(i))
println("---------------------")
// 2) 直接遍历所有元素,增强for循环
for (elem <- arr2) println(elem)
println("---------------------")
// 3) 迭代器
val iter = arr2.iterator
while (iter.hasNext)
println(iter.next())
println("---------------------")
// 4) 调用foreach方法
arr2.foreach((elem: Int) => println(elem))
arr.foreach(println)
println(arr2.mkString("--"))
println("========================")
// 4. 添加元素 由于创建的是不可变数组,增加元素,其实是产生新的数组)
val newArr = arr2.:+(73)
println(arr2.mkString("--"))//12--37--42--58--97
println(newArr.mkString("--"))//12--37--42--58--97--73
val newArr2 = newArr.+:(30)
println(newArr2.mkString("--"))//30--12--37--42--58--97--73
val newArr3 = newArr2 :+ 15
val newArr4 = 19 +: 29 +: newArr3 :+ 26 :+ 73
println(newArr4.mkString(", "))//19, 29, 30, 12, 37, 42, 58, 97, 73, 15, 26, 73
}
}
补充:map
map 对集合中的每个元素进行处理 , 将处理的结果返回 , 不要结果可以没有返回值
def map[B, That](f: A => B): That =
方法的参数是
f: A => B
f: (x:Any)=>{}
方法有返回值
val f = (e:Int)=>e*e
def main(args: Array[String]): Unit = {
val arr = Array[Int](1, 2, 3, 4)
// 对集合中的每个元素进行处理 , 将处理的结果返回 集合
val res:Array[Int] = arr.map(f)
val res2 = arr.map(x=>x*10)
// x=>x _ * 10
val res3 = arr.map( _ * 100)
// 可以不要
arr.map(println)
}
* map 处理每个元素 收集返回单额结果 也可以没有返回值
* foreach 常用于打印
* size 数组的长度 底层调用length
* length 数组长度
* min 最小值
* max 最大值
* sum 求和
* sorted 默认升序
* reverse 反转
* update ; arr(index) = v
* mkString 转换成字符串
* distinct 去重
* take(n) 从0号位置开始取n个元素
* takeRight(n) 从末尾取元素
* head 第一个元素
* tail 去除第一个元素 的子集合
* indexOf 返回一个元素的角标
* count统计符合条件的元素的个数
* find 查找符合要求的元素
7.2.2 可变数组
1)定义变长数组
val arr01 = ArrayBuffer[Any](3, 2, 5)
(1)[Any]存放任意数据类型
(2)(3, 2, 5)初始化好的三个元素
(3)ArrayBuffer 需要引入 scala.collection.mutable.ArrayBuffer
2)案例实操
(1)ArrayBuffer 是有序的集合
(2)增加元素使用的是 append 方法(),支持可变参数
package chapter07
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
object Test02_ArrayBuffer {
def main(args: Array[String]): Unit = {
// 1. 创建可变数组
val arr1: ArrayBuffer[Int] = new ArrayBuffer[Int]()
val arr2 = ArrayBuffer(23, 57, 92)
println(arr1)
println(arr2)
// 2. 访问元素
// println(arr1(0)) // error
println(arr2(1))
arr2(1) = 39
println(arr2(1))
println("======================")
// 3. 添加元素
val newArr1 = arr1 :+ 15
println(arr1)
println(newArr1)
println(arr1 == newArr1)
val newArr2 = arr1 += 19
println(arr1)
println(newArr2)
println(arr1 == newArr2)
newArr2 += 13
println(arr1)
77 +=: arr1
println(arr1)
println(newArr2)
arr1.append(36)
arr1.prepend(11, 76)
arr1.insert(1, 13, 59)
println(arr1)
arr1.insertAll(2, newArr1)
arr1.prependAll(newArr2)
println(arr1)
// 4. 删除元素
arr1.remove(3)
println(arr1)
arr1.remove(0, 10)
println(arr1)
arr1 -= 13 //删除元素13.若删除的元素不存在,则什么都不干
println(arr1)
// 5. 可变数组转换为不可变数组
val arr: ArrayBuffer[Int] = ArrayBuffer(23, 56, 98)
val newArr: Array[Int] = arr.toArray
println(newArr.mkString(", "))
println(arr)
// 6. 不可变数组转换为可变数组
val buffer: mutable.Buffer[Int] = newArr.toBuffer
println(buffer)
println(newArr)
}
}
控制台结果:
ArrayBuffer()
ArrayBuffer(23, 57, 92)
57
39
======================
ArrayBuffer()
ArrayBuffer(15)
false
ArrayBuffer(19)
ArrayBuffer(19)
true
ArrayBuffer(19, 13)
ArrayBuffer(77, 19, 13)
ArrayBuffer(77, 19, 13)
ArrayBuffer(11, 13, 59, 76, 77, 19, 13, 36)
ArrayBuffer(11, 13, 15, 59, 76, 77, 19, 13, 36, 11, 13, 15, 59, 76, 77, 19, 13, 36)
ArrayBuffer(11, 13, 15, 76, 77, 19, 13, 36, 11, 13, 15, 59, 76, 77, 19, 13, 36)
ArrayBuffer(15, 59, 76, 77, 19, 13, 36)
ArrayBuffer(15, 59, 76, 77, 19, 36)
23, 56, 98
ArrayBuffer(23, 56, 98)
ArrayBuffer(23, 56, 98)
[I@3d8c7aca
补充:
def main(args: Array[String]): Unit = {
val ab: ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)
// 向数组中添加元素
ab += 12
ab += 13 += 14
println(ab.length)
println(ab.mkString(" "))
// 删除元素
ab -= 2
println(ab.mkString(" "))
// 添加子集合
ab ++= (Array(4,5,6)) ++= (Array(7,8,9))
// --=
println(ab.mkString(" "))
}
def main(args: Array[String]): Unit = {
val arr = Array(1,2,3)
val ab: ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)
/**
* 插入数据
* 参数一 index
* 参数二 新元素
*/
ab.insert(0,11)
println(ab.mkString(" "))
// 清空数组
ab.clear()
println(ab.length)
println(ab.mkString(" - "))
ab.append(11,12,13)
println(ab.mkString(" - "))
/**
* 一个参数的
* index
* 二个参数
* start_index
* cnt
*/
// ab.remove(1,2)
ab.remove(1)
println(ab.mkString(" - "))
ab.insertAll(1,Array(1,2,3,4,5))
println(ab.mkString(" - "))
}
- += -=
- ++= --=
- insert (index ,e)
- append (e…)
- insertAll(index , Seq)
- clear
- remove(index , cnt)
7.2.3 不可变数组与可变数组的转换
1)说明
arr1.toBuffer //不可变数组转可变数组
arr2.toArray //可变数组转不可变数组
(1)arr2.toArray 返回结果才是一个不可变数组,arr2 本身没有变化
(2)arr1.toBuffer 返回结果才是一个可变数组,arr1 本身没有变化
2)案例实操
见上面
7.2.4 多维数组
1)多维数组定义
val arr = Array.ofDimDouble
说明:二维数组中有三个一维数组,每个一维数组中有四个元素
2)案例实操
package chapter07
object Test03_MulArray {
def main(args: Array[String]): Unit = {
// 1. 创建二维数组
val array: Array[Array[Int]] = Array.ofDim[Int](2, 3)
// 2. 访问元素
array(0)(2) = 19
array(1)(0) = 25
println(array.mkString(", "))
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))
}
}
7.3 列表 List
7.3.1 不可变 List
1)说明
(1)List 默认为不可变集合
(2)创建一个 List(数据有顺序,可重复)
(3)遍历 List
(4)List 增加数据
(5)集合间合并:将一个整体拆成一个一个的个体,称为扁平化
(6)取指定数据
(7)空集合 Nil
2)案例实操
package chapter07
object Test04_List {
def main(args: Array[String]): Unit = {
// 1. 创建一个List
val list1 = List(23, 65, 87) //数据有顺序,可重复
println(list1)
// 2. 访问和遍历元素
println(list1(1))
// list1(1) = 12 不可以的
list1.foreach(println)
// 3. 添加元素
val list2 = 10 +: list1
val list3 = list1 :+ 23
println(list1)
println(list2)
println(list3)
println("==================")
val list4 = list2.::(51)
println(list4)
val list5 = Nil.::(13)
println(list5)
val list6 = 73 :: 32 :: Nil //::的运算规则从右向左
val list7 = 17 :: 28 :: 59 :: 16 :: Nil
println(list7)
// 4. 合并列表
val list8 = list6 :: list7
println(list8)
val list9 = list6 ::: list7//两个list合并 将一个整体拆成一个一个的个体,称为扁平化
println(list9)
val list10 = list6 ++ list7 // ++相当于:::
println(list10)
}
}
补充:
* drop(n) 删除n个元素 返回新的集合
* isEmpty
* contains(e) 是否包含某个元素
* indexOf(e) 返回位置
* takeWhile
7.3.2 可变 ListBuffer
1)说明
(1)创建一个可变集合 ListBuffer
(2)向集合中添加数据
(3)打印集合数据
2)案例实操
package chapter07
import scala.collection.mutable.ListBuffer
object Test05_ListBuffer {
def main(args: Array[String]): Unit = {
// 1. 创建可变列表
val list1: ListBuffer[Int] = new ListBuffer[Int]()
val list2 = ListBuffer(12, 53, 75)
println(list1)
println(list2)
println("==============")
// 2. 添加元素
list1.append(15, 62)
list2.prepend(20)
list1.insert(1, 19, 22)
println(list1)
println(list2)
println("==============")
31 +=: 96 +=: list1 += 25 += 11
println(list1)
println("==============")
// 3. 合并list
val list3 = list1 ++ list2
println(list1)
println(list2)
println("==============")
//list1 ++=: list2 list1变,2不变
list1 ++=: list2 //list2基础上添加list1,list2变,list1不变
println(list1)
println(list2)
println("==============")
// 4. 修改元素
list2(3) = 30
list2.update(0, 89)
println(list2)
// 5. 删除元素
list2.remove(2)
list2 -= 25 //删除25
println(list2)
}
}
补充:
/**
* Author: Hang.Z
* Date: 21/05/26
* 集合中存储的类是java类
* User类 私有属性 吗公共的get set方法 JavaBean
* 封装数据使用
*/
object _05ListBufferDemo {
def main(args: Array[String]): Unit = {
// List集合存储java类
// 把类添加到集合中
val ls = ListBuffer[User]()
val user = new User()
user.setId(1)
user.setName("wbb")
val user2 = new User()
user2.setId(2)
user2.setName("wbb2")
ls.append(user)
ls.append(user2)
val users = user::user2::Nil
println(users)
}
}
class ScalaUser {
var id:Int =_
var name:String =_
override def toString: String = s"User{id=$id , name=$name}"
}
Vector
In general, except for the difference that Vector is indexed and List is not, the two classes work the same, so we’ll run through these examples quickly.
val nums = Vector(1, 2, 3, 4, 5)
val strings = Vector("one", "two")
val peeps = Vector(
Person("Bert"),
Person("Ernie"),
Person("Grover")
)
def main(args: Array[String]): Unit = {
val vs = Vector(1, 2, 3, 4, 5)
vs :+ 12
vs.foreach(println)
val ls: List[Int] = vs.toList
val buffer: mutable.Buffer[Int] = vs.toBuffer
val arr: Array[Int] = vs.toArray
}
7.4 Set 集合
默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用
scala.collection.mutable.Set 包
7.4.1 不可变 Set
1)说明
(1)Set 默认是不可变集合,数据无序
(2)数据不可重复
(3)遍历集合
2)案例实操
package chapter07
object Test06_ImmutableSet {
def main(args: Array[String]): Unit = {
// 1. 创建set
val set1 = Set(13, 23, 53, 12, 13, 23, 78)
println(set1)
println("==================")
// 2. 添加元素
val set2 = set1 + 129
println(set1)
println(set2)
println("==================")
// 3. 合并set
val set3 = Set(19, 13, 23, 53, 67, 99)
val set4 = set2 ++ set3
println(set2)
println(set3)
println(set4)
// 4. 删除元素
val set5 = set3 - 13
println(set3)
println(set5)
}
}
7.4.2 可变 mutable.Set
1)说明
(1)创建可变集合 mutable.Set
(2)打印集合
(3)集合添加元素
(4)向集合中添加元素,返回一个新的 Set
(5)删除数据
2)案例实操
package chapter07
import scala.collection.mutable
object Test07_MutableSet {
def main(args: Array[String]): Unit = {
// 1. 创建set
val set1: mutable.Set[Int] = mutable.Set(13, 23, 53, 12, 13, 23, 78)
println(set1)
println("==================")
// 2. 添加元素
val set2 = set1 + 11
println(set1)
println(set2)
set1 += 11
println(set1)
val flag1 = set1.add(10)
println(flag1)
println(set1)
val flag2 = set1.add(10)
println(flag2)
println(set1)
println("==================")
// 3. 删除元素
set1 -= 11
println(set1)
val flag3 = set1.remove(10)
println(flag3)
println(set1)
val flag4 = set1.remove(10)
println(flag4)
println(set1)
println("==================")
// 4. 合并两个Set
// val set3 =
}
}
7.5 Map 集合
Scala 中的 Map 和 Java 类似,也是一个散列表,它存储的内容也是键值对(key-value)
映射
7.5.1 不可变 Map
1)说明
(1)创建不可变集合 Map
(2)循环打印
(3)访问数据
(4)如果 key 不存在,返回 0
2)案例实操
package chapter07
object Test08_ImmutableMap {
def main(args: Array[String]): Unit = {
// 1. 创建map
val map1: Map[String, Int] = Map("a" -> 13, "b" -> 25, "hello" -> 3)
println(map1)
println(map1.getClass)
println("==========================")
// 2. 遍历元素
map1.foreach(println)
map1.foreach((kv: (String, Int)) => println(kv))
println("============================")
// 3. 取map中所有的key 或者 value
for (key <- map1.keys) {
println(s"$key ---> ${map1.get(key)}")
}
// 4. 访问某一个key的value
// 使用 get 访问 map 集合的数据,会返回特殊类型 Option(选项):有值(Some),无值(None)
println("a: " + map1.get("a").get)
println("c: " + map1.get("c"))
println("c: " + map1.getOrElse("c", 0))
println(map1("a"))
}
}
7.5.2 可变 Map
1)说明
(1)创建可变集合
(2)打印集合
(3)向集合增加数据
(4)删除数据
(5)修改数据
2)案例实操
package chapter07
import scala.collection.mutable
object Test09_MutableMap {
def main(args: Array[String]): Unit = {
// 1. 创建map
val map1: mutable.Map[String, Int] = mutable.Map("a" -> 13, "b" -> 25, "hello" -> 3)
println(map1)
println(map1.getClass)
println("==========================")
// 2. 添加元素
map1.put("c", 5)
map1.put("d", 9)
println(map1)
map1 += (("e", 7))
println(map1)
println("====================")
// 3. 删除元素
println(map1("c"))
map1.remove("c")
println(map1.getOrElse("c", 0))
map1 -= "d"
println(map1)
println("====================")
// 4. 修改元素
map1.update("c", 5)
map1.update("e", 10)
println(map1)
println("====================")
// 5. 合并两个Map
val map2: Map[String, Int] = Map("aaa" -> 11, "b" -> 29, "hello" -> 5)
// map1 ++= map2
println(map1)
println(map2)
println("---------------------------")
val map3: Map[String, Int] = map2 ++ map1
println(map1)
println(map2)
println(map3)
}
}
7.6 元组
1)说明
元组也是可以理解为一个容器,可以存放各种相同或不同类型的数据。说的简单点,就是将多个无关的数据封装为一个整体,称为元组。
注意:元组中最大只能有 22 个元素。
2)案例实操
(1)声明元组的方式:(元素 1,元素 2,元素 3)
(2)访问元组
(3)Map 中的键值对其实就是元组,只不过元组的元素个数为 2,称之为对偶
package chapter07
object Test10_Tuple {
def main(args: Array[String]): Unit = {
// 1. 创建元组
val tuple: (String, Int, Char, Boolean) = ("hello", 100, 'a', true)
println(tuple)
// 2. 访问数据
println(tuple._1)
println(tuple._2)
println(tuple._3)
println(tuple._4)
println(tuple.productElement(1))
println("====================")
// 3. 遍历元组数据
for (elem <- tuple.productIterator)
println(elem)
// 4. 嵌套元组
val mulTuple = (12, 0.3, "hello", (23, "scala"), 29)
println(mulTuple._4._2)
}
}
7.7 集合常用函数
7.7.1 基本属性和常用操作
1)说明
(1)获取集合长度
(2)获取集合大小
(3)循环遍历
(4)迭代器
(5)生成字符串
(6)是否包含
2)案例实操
package chapter07
object Test11_CommonOp {
def main(args: Array[String]): Unit = {
val list = List(1, 3, 5, 7, 2, 89)
val set = Set(23, 34, 423, 75)
// (1)获取集合长度
println(list.length)
// (2)获取集合大小
println(set.size)
// (3)循环遍历
for (elem <- list)
println(elem)
set.foreach(println)
// (4)迭代器
for (elem <- list.iterator) println(elem)
println("====================")
// (5)生成字符串
println(list)
println(set)
println(list.mkString("--"))
// (6)是否包含
println(list.contains(23))
println(set.contains(23))
}
}
7.7.2 衍生集合
1)说明
(1)获取集合的头
(2)获取集合的尾(不是头的就是尾)
(3)集合最后一个数据
(4)集合初始数据(不包含最后一个)
(5)反转
(6)取前(后)n 个元素
(7)去掉前(后)n 个元素
(8)并集
(9)交集
(10)差集
(11)拉链
(12)滑窗
2)案例实操
package chapter07
object Test12_DerivedCollection {
def main(args: Array[String]): Unit = {
val list1 = List(1, 3, 5, 7, 2, 89)
val list2 = List(3, 7, 2, 45, 4, 8, 19)
// (1)获取集合的头
println(list1.head)
// (2)获取集合的尾(不是头的就是尾)
println(list1.tail)
// (3)集合最后一个数据
println(list2.last)
// (4)集合初始数据(不包含最后一个)
println(list2.init)
// (5)反转
println(list1.reverse)
// (6)取前(后)n个元素
println(list1.take(3))
println(list1.takeRight(4))
// (7)去掉前(后)n个元素
println(list1.drop(3))
println(list1.dropRight(4))
println("=========================")
// (8)并集
val union = list1.union(list2)
println("union: " + union)
println(list1 ::: list2)
// 如果是set做并集,会去重
val set1 = Set(1, 3, 5, 7, 2, 89)
val set2 = Set(3, 7, 2, 45, 4, 8, 19)
val union2 = set1.union(set2)
println("union2: " + union2)
println(set1 ++ set2)
println("-----------------------")
// (9)交集
val intersection = list1.intersect(list2)
println("intersection: " + intersection)
println("-----------------------")
// (10)差集
val diff1 = list1.diff(list2)
val diff2 = list2.diff(list1)
println("diff1: " + diff1)
println("diff2: " + diff2)
println("-----------------------")
// (11)拉链 注:如果两个集合的元素个数不相等,那么会将同等数量的数据进行拉链,多余的数据省略不用
println("zip: " + list1.zip(list2))
println("zip: " + list2.zip(list1))
println("-----------------------")
// (12)滑窗
for (elem <- list1.sliding(3))
println(elem)
println("-----------------------")
for (elem <- list2.sliding(4, 2))
println(elem)
println("-----------------------")
for (elem <- list2.sliding(3, 3)) //滚动窗口
println(elem)
}
}
7.7.3 集合计算简单函数
1)说明
(1)求和
(2)求乘积
(3)最大值
(4)最小值
(5)排序
2)实操
package chapter07
object Test13_SimpleFunction {
def main(args: Array[String]): Unit = {
val list = List(5, 1, 8, 2, -3, 4)
val list2 = List(("a", 5), ("b", 1), ("c", 8), ("d", 2), ("e", -3), ("f", 4))
// (1)求和
var sum = 0
for (elem <- list) {
sum += elem
}
println(sum)
println(list.sum)
// (2)求乘积
println(list.product)
// (3)最大值
println(list.max)
println(list2.maxBy((tuple: (String, Int)) => tuple._2))
println(list2.maxBy(_._2))
// (4)最小值
println(list.min)
println(list2.minBy(_._2))
println("========================")
// (5)排序
// 5.1 sorted
val sortedList = list.sorted
println(sortedList)
// 从大到小逆序排序
println(list.sorted.reverse)
// 传入隐式参数
println(list.sorted(Ordering[Int].reverse))
println(list2.sorted)
// 5.2 sortBy
println(list2.sortBy(_._2))
println(list2.sortBy(_._2)(Ordering[Int].reverse))
// 5.3 sortWith
println(list.sortWith((a: Int, b: Int) => {
a < b
}))
println(list.sortWith(_ < _))
println(list.sortWith(_ > _))
}
}
(1)sorted
对一个集合进行自然排序,通过传递隐式的 Ordering
(2)sortBy
对一个属性或多个属性进行排序,通过它的类型。
(3)sortWith
基于函数的排序,通过一个 comparator 函数,实现自定义排序的逻辑。
7.7.4 集合计算高级函数
1)说明
(1)过滤
遍历一个集合并从中获取满足指定条件的元素组成一个新的集合
(2)转化/映射(map)
将集合中的每一个元素映射到某一个函数
(3)扁平化
(4)扁平化+映射 注:flatMap 相当于先进行 map 操作,在进行 flatten 操作
集合中的每个元素的子元素映射到某个函数并返回新集合
(5)分组(group)
按照指定的规则对集合的元素进行分组
(6)简化(归约)
(7)折叠
2)实操
package chapter07
object Test14_HighLevelFunction_Map {
def main(args: Array[String]): Unit = {
val list = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
// 1. 过滤
// 选取偶数
val evenList = list.filter((elem: Int) => {
elem % 2 == 0
})
println(evenList)
// 选取奇数
println(list.filter(_ % 2 == 1))
println("=======================")
// 2. 映射map
// 把集合中每个数乘2
println(list.map(_ * 2))
println(list.map(x => x * x))
println("=======================")
// 3. 扁平化
val nestedList: List[List[Int]] = List(List(1, 2, 3), List(4, 5), List(6, 7, 8, 9))
val flatList = nestedList(0) ::: nestedList(1) ::: nestedList(2)
println(flatList)
val flatList2 = nestedList.flatten
println(flatList2)
println("=======================")
// 4. 扁平映射
// 将一组字符串进行分词,并保存成单词的列表
val strings: List[String] = List("hello world", "hello scala", "hello java", "we study")
val splitList: List[Array[String]] = strings.map(_.split(" ")) // 分词
val flattenList = splitList.flatten // 打散扁平化
println(flattenList)
val flatmapList = strings.flatMap(_.split(" "))
println(flatmapList)
println("========================")
// 5. 分组groupBy
// 分成奇偶两组
val groupMap: Map[Int, List[Int]] = list.groupBy(_ % 2)
val groupMap2: Map[String, List[Int]] = list.groupBy(data => if (data % 2 == 0) "偶数" else "奇数")
println(groupMap)
println(groupMap2)
// 给定一组词汇,按照单词的首字母进行分组
val wordList = List("china", "america", "alice", "canada", "cary", "bob", "japan")
println(wordList.groupBy(_.charAt(0)))
}
}
3)Reduce 方法
Reduce 简化(归约) :通过指定的逻辑将集合中的数据进行聚合,从而减少数据,最
终获取结果。
案例实操
package chapter07
object Test15_HighLevelFunction_Reduce {
def main(args: Array[String]): Unit = {
val list = List(1, 2, 3, 4)
// 1. reduce
println(list.reduce(_ + _))
println(list.reduceLeft(_ + _))
println(list.reduceRight(_ + _))
println("===========================")
val list2 = List(3, 4, 5, 8, 10)
println(list2.reduce(_ - _)) // -24
println(list2.reduceLeft(_ - _))
println(list2.reduceRight(_ - _)) // 3 - (4 - (5 - (8 - 10))), 6
println("===========================")
// 2. fold
// fold 方法使用了函数柯里化,存在两个参数列表
// 第一个参数列表为 : 零值(初始值)
// 第二个参数列表为: 简化规则
println(list.fold(10)(_ + _)) // 10 + 1 + 2 + 3 + 4
println(list.foldLeft(10)(_ - _)) // 10 - 1 - 2 - 3 - 4
println(list2.foldRight(11)(_ - _)) // 3 - (4 - (5 - (8 - (10 - 11)))), -5
}
}
4)Fold 方法
Fold 折叠:化简的一种特殊情况。
(1)案例实操:fold 基本使用
见上面
(2)案例实操:两个集合合并
package chapter07
import scala.collection.mutable
object Test16_MergeMap {
def main(args: Array[String]): Unit = {
val map1 = Map("a" -> 1, "b" -> 3, "c" -> 6)
val map2 = mutable.Map("a" -> 6, "b" -> 2, "c" -> 9, "d" -> 3)
// println(map1 ++ map2)
val map3 = map1.foldLeft(map2)(
(mergedMap, kv) => {
val key = kv._1
val value = kv._2
mergedMap(key) = mergedMap.getOrElse(key, 0) + value
mergedMap
}
)
println(map3)
}
}
7.7.5 普通 WordCount 案例
1)需求
单词计数:将集合中出现的相同的单词,进行计数,取计数排名前三的结果
2)需求分析
3)案例实操
package chapter07
object Test17_CommonWordCount {
def main(args: Array[String]): Unit = {
val stringList: List[String] = List(
"hello",
"hello world",
"hello scala",
"hello spark from scala",
"hello flink from scala"
)
// 1. 对字符串进行切分,得到一个打散所有单词的列表
// val wordList1: List[Array[String]] = stringList.map(_.split(" "))
// val wordList2: List[String] = wordList1.flatten
// println(wordList2)
val wordList = stringList.flatMap(_.split(" "))
println(wordList)
// 2. 相同的单词进行分组
val groupMap: Map[String, List[String]] = wordList.groupBy(word => word)
println(groupMap)
// 3. 对分组之后的list取长度,得到每个单词的个数
val countMap: Map[String, Int] = groupMap.map(kv => (kv._1, kv._2.length))
// 4. 将map转换为list,并排序取前3
val sortList: List[(String, Int)] = countMap.toList
.sortWith(_._2 > _._2)
.take(3)
println(sortList)
}
}
7.7.6 复杂 WordCount 案例
package chapter07
object Test18_ComplexWordCount {
def main(args: Array[String]): Unit = {
val tupleList: List[(String, Int)] = List(
("hello", 1),
("hello world", 2),
("hello scala", 3),
("hello spark from scala", 1),
("hello flink from scala", 2)
)
// 思路一:直接展开为普通版本
val newStringList: List[String] = tupleList.map(
kv => {
(kv._1.trim + " ") * kv._2
}
)
println(newStringList)
// 接下来操作与普通版本完全一致
val wordCountList: List[(String, Int)] = newStringList
.flatMap(_.split(" ")) // 空格分词
.groupBy(word => word) // 按照单词分组
.map(kv => (kv._1, kv._2.size)) // 统计出每个单词的个数
.toList
.sortBy(_._2)(Ordering[Int].reverse)
.take(3)
println(wordCountList)
println("================================")
// 思路二:直接基于预统计的结果进行转换
// 1. 将字符串打散为单词,并结合对应的个数包装成二元组
val preCountList: List[(String, Int)] = tupleList.flatMap(
tuple => {
val strings: Array[String] = tuple._1.split(" ")
strings.map(word => (word, tuple._2))
}
)
println(preCountList)
// 2. 对二元组按照单词进行分组
val preCountMap: Map[String, List[(String, Int)]] = preCountList.groupBy(_._1)
println(preCountMap)
// 3. 叠加每个单词预统计的个数值
val countMap: Map[String, Int] = preCountMap.mapValues(
tupleList => tupleList.map(_._2).sum
)
println(countMap)
// 4. 转换成list,排序取前3
val countList = countMap.toList
.sortWith(_._2 > _._2)
.take(3)
println(countList)
}
}
7.8 队列
1)说明
Scala 也提供了队列(Queue)的数据结构,队列的特点就是先进先出。进队和出队的方
法分别为 enqueue 和 dequeue。
2)案例实操
package chapter07
import scala.collection.immutable.Queue
import scala.collection.mutable
import scala.collection.parallel.immutable
object Test19_Queue {
def main(args: Array[String]): Unit = {
// 创建一个可变队列
val queue: mutable.Queue[String] = new mutable.Queue[String]()
queue.enqueue("a", "b", "c")
println(queue)
println(queue.dequeue())
println(queue)
println(queue.dequeue())
println(queue)
queue.enqueue("d", "e")
println(queue)
println(queue.dequeue())
println(queue)
println("==========================")
// 不可变队列
val queue2: Queue[String] = Queue("a", "b", "c")
val queue3 = queue2.enqueue("d")
println(queue2)
println(queue3)
}
}
7.9 并行集合
1)说明
Scala 为了充分使用多核 CPU,提供了并行集合(有别于前面的串行集合),用于多核
环境的并行计算。
2)案例实操
package chapter07
import scala.collection.immutable
import scala.collection.parallel.immutable.ParSeq
object Test20_Parallel {
def main(args: Array[String]): Unit = {
val result: immutable.IndexedSeq[Long] = (1 to 100).map(
x => Thread.currentThread.getId
)
println(result)
val result2: ParSeq[Long] = (1 to 100).par.map(
x => Thread.currentThread.getId
)
println(result2)
}
}