Scala的集合有三大类:序列Seq、集Set、映射Map
在Scala中集合有可变(mutable)和不可变(immutable)两种类型(两个不同的包),
包的全局路径:scala.collection.immutable 默认使用的是该包中的集合
如果想使用可变的集合,就需要导包 scala.collection.mutable
immutable类型的集合初始化后就不能改变了(注意与val修饰的变量进行区别)
使用val这个关键字修饰一个变量(相当于java中的final),那么就意味着该变量的引用不可变,该引用中的内容是不是可变,取决于这个引用指向的集合的类型
集合框架整体架构

1. 数组
定长数组,长度不可变,但是内容可变。 默认是用的是定长数组
可变数组,长度,内容都是可变的。
Nothing是所有类型的子类型,表示程序出错了。
Null,所有引用类型的子类型,只有一个值,就是null
定长数组,是不可变的,长度不可变,内容可变,默认类型
变长数组,可变的,长度可变,内容可变
创建定长数组:
指定数组类型,并赋值,类型可省略,编译器会自动推导。
val arr1 = Array[Int](1,2,3,45)
通过new关键字创建的数组,必须指定数组的类型和长度。
val arr2 = new Array[Int](10)
取值赋值,下标从0开始:
arr1(0)
arr1(0)=100
// 清空
|
1.增强for循环
2.生成器 to或者until,0until 10 包含0不包含10
如何倒序输出??
|
toArray 变长数组转换成定长数组
toBuffer 定长数组转换成变长数组
yield关键字将原始的数组进行转换会产生一个新的数组,原始的数组不变
|
在Scala中,数组上的某些方法对数组进行相应的操作非常方便!
sorted默认是升序排序的。
arr. 然后输入Tab,可查看所有的方法。
val arr = Array(1,3,4,6,8)
数组反转:arr1.reverse
1. 元组Tuple
与数组或列表不同,元组可以容纳不同类型的对象,但它们也是不可变的。
元组是不同类型元素的集合
定义元组时,使用小括号将多个元素括起来,元素之间使用逗号分隔,元素的类型可以不同,元素的个数任意多个(不超过22个)
注意:元组没有可变和不可变之分,都是不可变的。
val t = (12.3, 1000, "spark") val t1 = new Tuple1(1) // 必须1个元素 val t4 = new Tuple4(1,2.0,"",3) // 必须4个元素 |
获取元组的值使用下标获取,但是元组的下标时从1开始的,而不是0
1.4. 拉链操作
zip命令可以将多个值绑定在一起,生成元组
val name=Array("xx1","xx2","xx3",”xx4”) val values=Array(1,2,3) name.zip(values) |
多个zip # name zip values zipvalues.map(_*10)
zipWithIndex 类似于zip,自带了索引,索引是从0 开始的。
注意:如果两个数组的元素个数不一致,拉链操作后生成的数组的长度为较小的那个数组的元素个数
1.5. 元素交换
可以使用 Tuple.swap 方法来交换对偶元组的元素。
|
元组类型Tuple1,Tuple2,Tuple3等等。目前在Scala中只能有22个上限,如果需要更多个元素,那么可以使用集合而不是元组
不可变list 长度不可变,内容也不可变 List
可变list 长度和内容都可变 ListBuffer
1.1. 不可变序列
默认就是不可变序列,长度和内容都不可变
构造列表的两个基本单位是 Nil 和 ::
Nil 表示为一个空列表。
创建List集合的两种方式:
val list1= List[Int](1,2,3)
val list2 = 9::5::2::Nil
注意::: 操作符是右结合的,该操作符就是将给定的头和尾创建一个新的列表
如9 :: 5 :: 2 :: Nil相当于 9 ::(5 :: (2 :: Nil))
注意:在Scala中列表要么为空,要么是一个head元素加上一个tail列表。
列表的连接:
可以使用++ 或 ::: 运算符或或 List.concat() 方法来连接两个或多个列表
注意:对不可变List的所有的操作,全部生成新的List
lst1.head // 列表的尾列表 |
List和Array的对比:
list不可变,表示长度不可变,内容也不可变
array 长度不可变,但是内容可变
不可变list和可变List的比较(List和ListBuffer):
不可变List,长度不可变,值不可变
可变List,长度可变,值可变
1.2. 可变序列
ListBuffer
需要显示导包import scala.collection.mutable._
创建ListBuffer的两种方式:
val lb1 = ListBuffer[Int]() // 创建的同时可赋初值
val lb2 = new ListBuffer[Int]() // 类型必须显示指定
添加元素:
+=方法和append方法,都可以添加多个元素。
val lst4 = 5 +: lst0 // 去除元素 lb2.remove(1,2) //去除元素 第一个参数是下标,第二个参数的个数 // 判断集合是否为空 Lb2.isEmpty() |
List的转换:
可变list可以通过toList方法,生成新的List
list可以通过toBuffer,转变成ArrayBuffer
2. 映射Map
在Scala中,把哈希表这种数据结构叫做映射
映射是K/V对 类型的值。
可变的map,还是不可变的map,都是Map
2.1. 定义map
在Scala中,有两种Map,一个是immutable包下的Map,该Map中的内容不可变;另一个是mutable包下的Map,该Map中的内容可变。
默认是immutable包下的map,
// 默认是immtable包下的Map val mp1 = Map(("a",1),("b",2)) |
可使用mutable.Map
|
针对可变集合,多种赋值方式
mp4 += ("e"->8, "f"->9) |
2.3. 获取映射值
判断key是否存在 contains
mp4.contains(“b”)
mp4(“a”)
mp4.get(“xxoo”)
如果没有值,赋予默认值:
mp4.getOrElse(“xxoo”,9527)
2.4. 赋值和修改值
m1.getOrElse("d",0)
m1("b") =22
m1.updated("b",22)// 如果是不可变的Map,那么会生成一个新的map集合
2.5. 删除元素
根据key来删除一个或多个值
m1 -= ("a")
m1.remove("a")
去除多个key:
m1 -=("a","b")
m1 --= List(“key”)
2.6. map遍历
for(i <- mp) println(i)
for((k,v) <- mp){println(k)}
for((_,v) <- mp){println(v)}
_是占位符,如果只需要遍历value,不需要遍历key,就可以用占位符
交换k,v
for((k,v) <- mp)yield (v,k)
mp.map(x=>(x._2,x._1))
mp.map(x=>x.swap)
2.7. 获得keys和values
合并
使用 ++ 运算符或 mp.++() 方法来连接两个 Map,Map 合并时会移除重复的 key。
// 合并时,相同的key元素会被覆盖
|
如果需要用到可变的Map和不可变的Map.
不导入具体的类,而是导入包名,在使用的时候,直接使用包名. 类
// import scala.collection.mutable.Map import scala.collection.mutable valmp2 = mutable.Map("a" -> 1) |
方法的使用
map 迭代集合中的每一个元素,然后按照自己的逻辑来修改元素
map方法操作集合中的每一个元素,返回值类型。
map方法有一个参数,是函数类型,该函数作用于集合的每一个元素上,对集合的每一个元素执行操作。有返回值。
map方法的内层返回值,是由函数的返回值决定的。
flatten 压平 如果有嵌套集合,就会把内层的嵌套去掉了
flatMap 先map 再flatten 先map 再压平
foreach 对每一个元素执行操作,相当于遍历 println 返回值是Unit
filter 过滤
map和foreach的区别:
1,底层实现不同,map方法利用隐式转换实现的Builder,foreach底层使用的是迭代器。
2,返回值不同,map返回值类型一般由函数返回值类型决定(map方法的参数就是一个函数),foreach返回值为Unit
怎么选择?如果要求有返回值,就用map,如果是打印或者没有返回值的要求,使用foreach。
|
4. 案例wordCount
|
今日总结:
1, 函数和方法之间的区别和联系,特别是函数作为方法的参数。
2, 基本的集合框架。数组,元组,List,Map
3, 集合的常用方法 map flatMap flatten filter foreach
4, wordcount
5. Set
不可变Set,可变Set
5.1. 不可变的Set
长度和值都不可变,set中的元素不能重复
|
5.2. 可变的Set
可变Set中,remove方法,移除的是元素,而不是下标
ListBuffer中,remove方法,参数是下标
|
6. Map和Option
mp.get(key)的返回值类型是Option[value的类型]
Option 类型,表示,值可能有,也可能没有
Option抽象类有两个子类,
一个是None,单例的,表示key不存在
一个是Some,多例的。Some(value) Some(value).get
在Scala中Option类型样例类用来表示可能存在或也可能不存在的值(Option的子类有Some和None)。Some包装了某个值,None表示没有值。
|
7. 集合常用的方法
map
filter
过滤出满足条件的所有元素,并返回一个集合
filterNot
过滤出不满足条件的所有元素,并返回一个集合
find
过滤出满足条件的一个元素,并返回一个Option
如果说有结果值,返回值的是Some(元素值),通过get方法来获取值
sorted
按元素的升序排序
sortBy
按照指定的条件排序
sortWith
接收两个参数,并进行比较
mapValues
类似于map,只是处理的是k-v类型中的v值,只能作用于map类型集合
1, 只能操作map集合
2, 作用于map集合中的values,然后返回map集合,也就是说map中的key是不变的
groupBy
按照指定条件分组
grouped grouped(size: Int): Iterator
按照指定元素个数进行分组
count def count(p: A => Boolean): Int
统计满足条件的元素个数
A: 取决于元素的类型。 Array[(String,Int)] à A: (String,Int) Array[Int] à A: Int
reduce *****
元素归并
参数是一个函数,这个函数有两个参数 累加值 元素值 调用的就是reduceLeft
val arr=Array("aa","bb","cc","dd") arr.reduce((x,y)=>自定义操作) 自定义操作的方法,必须是x数据类型上支持的方法。x可以是任意类型 arr.reduce(_ + _) arr.reduce(_ ++ _) val lst = List(List("a"),List("b"),List("c")) lst.reduce(_++_) lst.reduce(_:::_) |
reduceLeftreduceRight
reduce底层调用的就是reduceLeft,只不过,reduce要求函数的输入类型和返回值类型必须一致,而reduceLeft,可以不一致。
val arr = Array(1,3,5,7,9)
reduce(_ - _) reduce((a,b)=>a-b)
false ---> true a:累加值 b:元素值 1 1 3 1 3 1-3 -2 5 -2 5 -2 - 5 -7 7 -7 7 -7-7 -14 9 -14 9 -14 - 9 -23
(((((1)-3)-5)-7)-9) -23 reduce reduceLeft
(1-(3-(5-(7-(9))))) 5 |
reduce -à reduceLeft
区别: reduce的2个输入参数类型,和输出值类型必须一致,
reduceLeft,可以支持两个不同类型的输入参数。
reduce[A1 >: A](op: (A1, A1) => A1) reduceLeft[B >: A](op: (B, A) => B) |
reduce
foldfoldLeft foldRight
deffold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 def foldLeft[B](z: B)(op: (B, A) => B): B
|
fold(0)(_+ _)
fold有两个参数,第一个参数是默认值,第二个参数是一个函数,该函数有两个参数 累加值 元素值 调用的就是foldLeft
fold 要求函数的2个输入参数类型必须一致,foldLeft 可以允许函数的2个输入参数类型
不一致
fold foldLeft foldRight 相比于 reduce reduceLeft reduceRight ,多了一个初始值参数运算。其他的都一样,+ ++ 取决于 元素的类型。
示例:求平均值 val d1 = Array(("bj",28.1), ("sh",28.7), ("gz",32.0), ("sz", 33.1))
|
交集,并集 差集
intersect union diff
union是一个轻量级的方法,union没有去重
//比较常用的方法:先union,然后再分组
distinct 元素去重
mkString 把集合中的所有元素拼接成字符串
mkString(分隔符)
arr1.reduce(_+"-" + _)
arr1.mkString("-")
take(n) 获取集合中前几个元素 没有排序
slice(from,until) 截取元素,提取元素列表中的from 到until位置的元素
根据角标获取元素的值, [ )
聚合 aggregate
val arr = List(List(1, 2, 3), List(2))
val result = arr.aggregate(0)(_+_.sum, _+_)