一、集合简介
1.1 集合简介
1)Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质。
2)对于几乎所有的集合类,Scala都同时提供了可变和不可变的版本,分别位于以下两个包
不可变集合:scala.collection.immutable
可变集合: scala.collection.mutable
3)Scala不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而不会对原对象进行修改。类似于java中的String对象
4)可变集合,就是这个集合可以直接对原对象进行修改,而不会返回新的对象。类似于java中StringBuilder对象
建议:在操作集合的时候,不可变用符号,可变用方法
1.2 不可变集合继承图:
![](https://img-blog.csdnimg.cn/img_convert/3e2b3b3e4207bae9769693bd7d447e10.png)
1.3 可变集合继承图:
![](https://img-blog.csdnimg.cn/img_convert/3c85b121af6d253672ff6a739c3f285c.png)
二、数组
2.1 不可变数组
1)定义数组
方式一:val arr1 = new Array[Int](10)
1. new是关键字
2. [Int]是指定可以存放的数据类型,如果希望存放任意数据类型,则指定Any
3. (10)表示数组的大小,确定后就不可以变化
方式二:val arr2 = Array(1,2,3,4,5);
1. 在定义数组时,直接赋初始值
object ImmutableArray {
def main(args: Array[String]): Unit = {
// 1. 创建数组
val arr1 = new Array[Int](5);
// 另一种创建方式
val arr2 = Array(1,2,3,4,5);
// 2. 访问元素
arr1(0) = 12
arr1(1) = 23
println(arr1(0)) // 12
println(arr1(1)) // 23
println(arr1(2)) // 0
}
// 3. 数组的遍历
// 1) 普通for循环
for(i <- 0 until arr1.length){
println(arr1(i))
}
for(i <- arr1.indices) println(arr1(i))
// 2) 遍历所有元素,增强for循环
for(elem <- arr2)println(elem)
// 3) 迭代器
val iter = arr1.iterator
while (iter.hasNext) println(iter.next())
// 4) 调用foreach方法
arr1.foreach( println )
// 5) 调用函数
println(arr1.mkString("-"))
// 4. 不可变数组添加元素
val arr11 = arr1:+10
println(arr11.mkString("-")) // 数字加在后面:12-23-0-0-0-10
val arr12 = 11+:arr1
println(arr12.mkString("-")) // 数字加在前面:11-12-23-0-0-0
}
2.2 可变数组
object ArrayBuffer {
def main(args: Array[String]): Unit = {
// 1. 创建可变数组
val arr1 = new ArrayBuffer[Int]()
val arr2 = ArrayBuffer(12,23,34,45)
// 2. 访问元素
println(arr1(0)) // error越界异常
println(arr2(0)) // 12
// 3. 添加元素
arr1 += 11
println(arr1.mkString(",")) // 数字加在后面
12 +=: arr1
println(arr1.mkString(",")) // 数字加在前面
arr1.append(13)
arr1.prepend(14)
arr1.insert(1, 0,10)
arr1.insertAll(2,arr2)
arr1.appendAll(arr2)
arr1.prependAll(arr2)
// 4. 删除元素
arr1.remove(3) // 删除第3个元素
arr1.remove(0, 10) // 删除从0开始的10个元素
arr1 -= 11
}
}
2.3 可变数组、不可变数组的相互转化
// 1. 可变数组转换为不可变数组
val arr = ArrayBuffer(23,34,45)
val newArr = arr.toArray
println(newArr.mkString(","))
// 2. 不可变数组转换为可变数组
val arrBuffer = newArr.toBuffer
println(arrBuffer)
2.4 多维数组
object MulArray {
def main(args: Array[String]): Unit = {
// 1. 创建二维数组
val array = Array.ofDim[Int](2,3)
// 2. 访问元素
array(0)(1) = 10
array(1)(0) = 21
// 二位数组相当于保存了两个一维数组的地址。
println(array.mkString(", ")) // [I@2d209079, [I@6bdf28bb
// 方式一:for循环输出
for(i<-0 until array.length; j<- 0 until array(i).length){
println(array(i)(j))
}
// 方式二:使用indices函数
for(i<-array.indices; j<-array(i).indices){
print(array(i)(j)+"\t")
if(j==array(i).length - 1) println()
}
// 方式三:增强for
array.foreach(_.foreach( println ))
}
}
三、列表List
3.1 不可变List
1)说明
(1)List默认为不可变集合
(2)创建一个List(数据有顺序,可重复)
(3)遍历List
(4)List增加数据
(5)集合间合并:将一个整体拆成一个一个的个体,称为扁平化
(6)取指定数据
(7)空列表Nil
object Test_List {
def main(args: Array[String]): Unit = {
// 1. 创建一个List
val list1 = List(23,34,45)
println(list1) // List(23, 34, 45)
// 2. 访问和遍历元素
println(list1(1))
list1.foreach(println)
//3. 添加元素
val list2 = list1.+:(10) // :+ 在列表末尾添加元素
val list3 = 10 +: list1 // +: 在列表开头添加元素
// ::添加元素
val list4 = list2.::(51) // ::表示在列表开头添加元素
val list4 = Nil.::(15) // 可以用于在空列表中添加元素
val list5 = 15 :: Nil // 这种方法也可以添加元素
// 结合Nil,可以使用如下创建列表的方法:
val list6 = 12 :: 23 :: 34 :: 45 :: Nil
// 4. 合并列表。也可以使用上面::的方式
// :: 基于list6添加元素,添加的这个元素是一个List列表
val list7 = list5 :: list6 // List(List(15), 12, 23, 34, 45)
// ::: 把两个列表的元素进行拆分,合并成一个列表
val list8 = list5 ::: list6 // List(15, 12, 23, 34, 45)
val list9 = list5 ++ list6 // 和:::功能一致,底层调用的是:::方法
}
3.2 可变列表ListBuffer
object Test_ListBuffer {
def main(args: Array[String]): Unit = {
// 1. 创建可变列表
val list1 = new ListBuffer[Int]()
val list2 = ListBuffer(12, 23, 34)
// 2. 添加元素
list1.append(11, 22) // 在list末尾添加元素
list1.prepend(33, 44) // 在list开头添加元素
list1.insert(1, 10, 20) // 在指定位置(下标为1)插入元素
list1 += 25 += 35 // 在list末尾添加元素
15 +=: list1 // 在list开头添加元素
// 3. 合并list
val list3 = list1 ++ list2 // list1、list2没有变化,生成新列表list3
list1 ++= list2 // list1末尾添加list2
// 4. 修改元素
list2(1) = 30
list2.update(2,44)
// 5. 删除元素
list2.remove(2)
list2 -= 30 // -=删除的是匹配到的第一个元素
}
}
四、Set集合
默认情况下,Scala使用的是不可变集合。如果想使用可变集合,需要引用scala.collection.mutable.Set包。
4.1 不可变Set
1)说明
(1)Set默认是不可变集合,数据无序
(2)数据不可重复
(3)遍历集合
2)案例实操
object ImmutableSet {
def main(args: Array[String]): Unit = {
// 1. 创建Set
val set1 = Set(12,23,23,31)
println(set1) // 数据自动去重
// 2. 添加元素
val set2 = set1 + 20
println(set2) // 无序,插入数据位置随机
// 3. 合并Set
val set3 = Set(12,45,32,34)
val set4 = set2 ++ set3
println(set4)
// 4. 删除元素
val set5 = set3 - 12
println(set3) // set3元素不变
println(set5) // set5在set3的基础上少了元素12
}
}
4.2 可变mutable.Set
object MutableSet {
def main(args: Array[String]): Unit = {
// 1. 创建Set
import mutable.Set
val set1 = Set(12,23,23,31)
// 或者在声明时加入包名
val set1 = mutable.Set(12,23,23,31)
// 2. 添加元素
val set2 = set1 + 20
println(set2) // +运算 set1内容不作改变
set1 += 11 // 将添加新元素后的集合赋值给set1
set1.add(12)
// 3. 删除元素
set1 -= 11
set1.remove(12)
// 4. 合并两个Set
val set3 = mutable.Set(13,24,36)
val set4 = set1 ++ set3 // set1、set3元素不变
set1 ++= set3 // set1中添加set3的元素
}
}
五、Map集合
Scala中的Map和Java类似,也是一个散列表,它存储的内容也是键值对(key-value)映射
5.1 不可变Map
1)说明
(1)创建不可变集合Map
(2)循环打印
(3)访问数据
(4)如果key不存在,返回0
2)案例实操
object ImmutableMap {
def main(args: Array[String]): Unit = {
// 1. 创建map
val map1 = Map[String, Int]("a"->13,"b"->25,"hello"->3)
println(map1)
// 2. 遍历元素
map1.foreach(println)
map1.foreach( (kv: (String, Int)) => println(kv) )
// 3. 取map中所有的key 或者 value
for (key <- map1.keys){
println(s"$key -> $(map1.get(key))")
}
// 4. 访问某一个key的value
println( map1.get("a") ) // Some(13)
println(map1.get("a").get) // 13
// 若key不存在,输出None。但key不存在,无法调用.get方法,回出现异常
// 为了安全起见,我们有getOrElse方法,若不存在,输出0
println(map1.getOrElse("c",0))
}
}
5.2 可变Map
object ImmutableMap {
def main(args: Array[String]): Unit = {
// 1. 创建map
val map1 = mutable.Map[String, Int]("a"->13,"b"->25,"hello"->3)
println(map1)
// 2. 添加元素
map1.put("c", 5)
map1.put("d", 9)
map1 += (("e", 7)) // 外层()表示方法调用,内层()表示键值对
// 3. 删除元素
map1.remove("e")
map1 -= "d"
// 4. 修改元素
map1.update("c", 5)
map += (("e", 10))
// 5. 合并两个Map
val map2 = Map[String, Int]("aaa"->13,"b"->29,"hello"->5)
map1 ++= map2 // map2中的值全部添加到map1中,没有的值添加,有的覆盖
}
}
六、Tuple元组
1)说明
元组也是可以理解为一个容器,可以存放各种相同或不同类型的数据。说的简单点,就是将多个无关的数据封装为一个整体,称为元组。
注意:元组中最大只能有22个元素。
![](https://img-blog.csdnimg.cn/img_convert/9fcbb1cb88afccecccdf31496652a9ea.png)
2)案例实操
(1)声明元组的方式:(元素1,元素2,元素3)
(2)访问元组
(3)Map中的键值对其实就是元组,只不过元组的元素个数为2,称之为对偶
object TestTuple {
def main(args: Array[String]): Unit = {
// 1. 创建元组
val tuple = Tuple3("hello",1,true)
// 2. 访问元组
println(tuple) // (hello,1,true)
// 访问元组的1个元素
println(tuple._1) // hello
// 交换后输出(swap方法是Tuple2特有方法)
println(tuple2.swap) // (name,2)
// 3. 遍历元组数据
for (elem <- tuple.productIterator)
println(elem)
// 4. 嵌套元组
val mulTuple = (12, 0.3, "hello", (23, "scala"), 29)
println(mulTuple._4._2) // 访问元组中嵌套元组的元素
}
}
七、集合常用函数
7.1 基本属性和常用操作
1)说明
(1)获取集合长度
(2)获取集合大小
(3)循环遍历
(4)迭代器
(5)生成字符串
(6)是否包含
2)案例实操
object CommonOperation {
def main(args: Array[String]): Unit = {
val list = List(1,3,5,7,2,89)
val set = Set(23,34,523,65)
// (1)获取集合长度
println(list.length)
// (2)获取集合大小
println(set.size)
// (3)循环遍历
for (elem <- list)
println(elem)
set.foreach(println)
// (4)迭代器
for (elem <- list.iterator) println(elem)
// (5)生成字符串
println(list)
println(set)
println(list.mkString("--"))
// (6)是否包含
println(list.contains(23))
println(set.contains(523))
}
}
7.2 衍生集合
1)说明
(1)获取集合的头
(2)获取集合的尾(不是头就是尾)
(3)集合最后一个数据
(4)集合初始数据(不包含最后一个)
(5)反转
(6)取前(后)n个元素
(7)去掉前(后)n个元素
(8)并集
(9)交集
(10)差集
(11)拉链
(12)滑窗
2)案例实操
object DerivedCollection {
def main(args: Array[String]): Unit = {
val list1 = List(1,3,5,7,2,89)
val list2 = List(3,7,2,45,7,4,8,19)
// (1)获取集合的头
println(list1.head) // 1
// (2)获取集合的尾(不是头就是尾)
println(list1.tail) // List(3, 5, 7, 2, 89)
// (3)集合最后一个数据
println(list1.last) // 89
// (4)集合初始数据(不包含最后一个)
println(list1.init) // List(1, 3, 5, 7, 2)
// (5)反转
println(list1.reverse) // List(89, 2, 7, 5, 3, 1)
// (6)取前(后)n个元素
println(list1.take(3)) // List(1, 3, 5)
println(list1.takeRight(4)) // List(5, 7, 2, 89)
// (7)去掉前(后)n个元素
println(list1.drop(3)) // List(7, 2, 89)
println(list1.dropRight(4)) // List(1, 3)
// (8)并集
val union = list1.union(list2)
println("union: " + union) // 等同于 ::: list1:::list2
// (如果是set做丙级,会去重)
val set1 = Set(1,3,5)
val set2 = Set(2,3,4)
val union2 = set1.union(set2)
println("union2: " + union) // 等同于 ++ set1++set2
// (9)交集
val itersection = list1.intersect(list2) // List(3, 7, 2)
// (10)差集
val diff1 = list1.diff(list2)
val diff2 = list2.diff(list1)
println(diff1) // List(1, 5, 89)
println(diff2) // List(45, 7, 4, 8, 19)
// (11)拉链
println("zip:"+ list1.zip(list2)) // zip:List((1,3), (3,7), (5,2), (7,45), (2,7), (89,4))
println("zip:"+ list2.zip(list1)) // zip:List((3,1), (7,3), (2,5), (45,7), (7,2), (4,89))
// (12)滑窗
for( elem <- list1.sliding(3) ) // iterator类型,滑动窗口
println(elem) // 即使数据不全,最后一个窗口也要把全部元素列出来
for( elem <- list1.sliding(3, 4) ) // iterator类型,滚动窗口.步长为4
println(elem)
}
}
7.3 集合计算初级函数
1)说明
(1)求和
(2)求乘积
(3)最大值
(4)最小值
(5)排序
2)实操
object SimpleFunction {
def main(args: Array[String]): Unit = {
val list = List(5,1,8,2,-3,4)
// (1)求和
println(list.sum)
// (2)求乘机
println(list.product)
// (3)最大值
println(list.max)
// 如果list中不是字符,需要自定义比较方式
val list2 = List( ("a",5),("b",1),("c",5),("d",1) )
println( list2.maxBy( (tuple:(String, Int)) => tuple._2 ))
// 可简写为如下:
println( list2.maxBy( _._2 ))
// (4)最小值
println(list.min)
println( list2.minBy( _._2 ))
// (5)排序
// 5.1 sort
println(list.sorted) // List(-3, 1, 2, 4, 5, 8)
// 从大到小排序
println(list.sorted.reverse)
// 5.2 sortBy
println(list2.sortBy(_._2)) // List((b,1), (d,1), (a,5), (c,5))
// 5.3 sortWith
println(list.sortWith( (a:Int, b:Int)=> {a < b} ))
println(list.sortWith( _ < _ ))
}
}
7.4 集合计算高级函数
1)说明
(1)过滤filter
遍历一个集合并从中获取满足指定条件的元素组成一个新的集合
(2)转化/映射(map)
将集合中的每一个元素映射到某一个函数
(3)扁平化flatten
(4)扁平化+映射flatMap
注:flatMap相当于先进行map操作,再进行flatten操作
集合中的每个元素的子元素映射到某个函数并返回新集合
(5)分组(groupBy)
按照指定的规则对集合的元素进行分组
(6)简化(归约)reduce
(7)折叠fold
2)实操
object HighLevelFunction {
def main(args: Array[String]): Unit = {
val list = List(1,2,3,4,5,6,7,8,9)
// (1)过滤
// 选取偶数
val evenList = list.filter( x => x%2==0 )
println(evenList)
// 可以省略为
println(list.filter( _ % 2 == 0 ))
// (2)转化/映射(map)
// 把集合中的每个数乘2
println(list.map(_ * 2))
println(list.map( x => x * x ))
// (3)扁平化flatten
val nestedList = List(List(1,2,3),List(4,5),List(6,7,8,9))
println(nestedList.flatten) // List(1, 2, 3, 4, 5, 6, 7, 8, 9)
// (4)扁平化+映射
// 将一组字符串进行分词,并保存成单词的列表
val strings = List("hello world","hello scala","hello java")
val splitList = strings.map(string => string.split(" ")) // 分词
val flattenList = splitList.flatten // 打散扁平化
println(flattenList) // List(hello, world, hello, scala, hello, java)
// 上面两步可以省略为flatMap
val flatmapList = strings.flatMap(_.split(" ")) // List(hello, world, hello, scala, hello, java)
println(flatmapList)
// (5)分组(groupBy)
// 分成奇偶两组
val groupBy = list.groupBy(_ % 2)
val groupBy2 = list.groupBy( data => {
if(data % 2 == 0) "偶数" else "奇数"
})
println(groupBy) // Map(1 -> List(1, 3, 5, 7, 9), 0 -> List(2, 4, 6, 8))
println(groupBy2) // Map(奇数 -> List(1, 3, 5, 7, 9), 偶数 -> List(2, 4, 6, 8))
// 给定一组词汇,按照单词的首字母进行分组
val wordList = List("china","america","alice","canada","bob","japan")
println(wordList.groupBy( _.charAt(0) ))
// Map(b -> List(bob), j -> List(japan), a -> List(america, alice), c -> List(china, canada))
}
}
object HighLevelFunction_Reduce {
def main(args: Array[String]): Unit = {
val list = List(1,2,3,4)
// 1. reduce
println(list.reduce( _+_ )) // 10
println(list.reduceLeft( _+_ )) // 10
println(list.reduceRight( _+_ )) // 10
val list2 = List(3,4,5,8,10)
println(list2.reduce( _-_ )) // -24
println(list2.reduceLeft( _-_ )) // -24
println(list2.reduceRight( _-_ )) // 6 3-(4-(5-(8-10)))
// 2. fold
println(list.fold(10)(_+_)) // 20 10 + 1 + 2 + 3 + 4
println(list.fold(10)(_-_)) // 0 10 - 1 - 2 - 3 - 4
println(list2.foldRight(11)(_-_)) // -5 3 - (4 - (5 - (8 - (10 -11))))
}
}
7.5 普通WordCount案例
1)需求
单词计数:将集合中出现的相同的单词,进行计数,取计数排名前三的结果
2)需求分析
object CommonWordCount {
def main(args: Array[String]): Unit = {
val stringList = List(
"hello",
"hello world",
"hello scala",
"hello spark from scala",
"hello flink from scala"
)
// 1. 对字符串进行切分,得到一个打散所有单词的列表
val wordList = stringList.flatMap(_.split(" "))
println(wordList)
// 2. 相同的单词进行分组
val groupMap = wordList.groupBy(word=>word)
println(groupMap)
// 3. 对分组之后的list取长度,得到每个单词的个数
val countMap = groupMap.map(kv=>(kv._1,kv._2.length))
println(countMap)
// 4. 将map转换为list,并排序取前三
val sortList = countMap.toList.sortWith(_._2>_._2).take(3)
println(sortList)
}
}
八、队列
1)说明
scala也提供了队列(Queue)的数据结构,队列的特点就是先进先出。进队和出队的方法分别为enqueue和dequeue。
2)案例实操
object TestQueue {
def main(args: Array[String]): Unit = {
// 创建一个可变队列
val que = new mutable.Queue[String]()
que.enqueue("a","b","c")
println(que) // Queue(a, b, c)
println(que.dequeue()) // a
println(que.dequeue()) // b
println(que) // Queue(c)
// 不可变队列
val que2 = Queue("a","b","c")
println(que2) // Queue(a, b, c)
val que3 = que2.enqueue("d")
println(que3) // Queue(a, b, c, d)
}
}
九、并行集合par
1)说明
Scala为了充分说明多核CPU,提供了并行集合(有别于前面的串行集合),用于多核环境的并行计算。
2)案例实操
object TestPar {
def main(args: Array[String]): Unit = {
val result = (1 to 100).map(
x => Thread.currentThread.getId
)
println(result)
val result2 = (1 to 100).par.map(
x => Thread.currentThread.getId
)
println(result2)
}
}