集合简介

  1. Scala中有三大类:序列Seq、集Set、映射Map(都是trait),所有集合都扩展自Iterable。而Java中List、Set继承自Collection,Map独立
  2. 对于所有集合类,Scala提供了可变和不可变的版本,分别位于以下两个包
    1. 不可变集合: scala.collection.immutable
    2. 可变集合:scala.collection.mutable
  3. Scala不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而不会对原对象的进行修改,类似java中String
  4. Scala可变集合,就是指该集合可以直接对原对象进行修改,而不会返回新的对象,类似java中StringBuilder对象
  • 建议:在操作集合的时候,不可变用符号,可变用方法

集合 - 图1
不可变集合类型↑

Traversable

是一个特质,他是其它集合的父特质,他的子特质immutable.Traversable和mutable.Traversabel分别是不可变集合和可变集合的父特质。集合中大部分通用方法在这个特质中定义

  1. // 创建空Traversable对象
  2. val t1 = Traversable.empty[Int]
  3. val t2 = Traversable[Int]()
  4. val t3 = Nil
  5. // 创建带参数的对象
  6. val t1 = List(1, 2, 3).toTraversable
  7. val t2 = Traversable(1,2,3)//伴生apply方法
  8. // 比较是否不同
  9. println(t1 == t2) // 比较集合中的数据
  10. println(t1 == t3)
  11. println(t3 == t2)
  12. println(t1 eq t2) // 比较集合的地址
  13. println(t1 eq t3)
  14. println(t3 eq t2)

Traversable是一个特质,具体的实现还是依靠子类实现

案例:转置Traversable集合

Traversable集合t1,有三个元素,每个元素都是Traversable集合分别存储(1,4,7),(2,5,8),(3,6,9),进行转置
transpose

  1. def main(args: Array[String]): Unit = {
  2. val t1: Traversable[Traversable[Int]] = Traversable(Traversable(1,4,7),Traversable(2,5,8),Traversable(3,6,9))
  3. val t2: Traversable[Traversable[Int]] = t1.transpose
  4. }

案例:拼接集合

创建大量临时集合,使用concat()方法提高效率

  1. def main(args: Array[String]): Unit = {
  2. val t1 = Traversable(11, 22, 33)
  3. val t2 = Traversable(44, 55)
  4. val t3 = Traversable(66,77,88,99)
  5. val t4 = Traversable.concat(t1,t2,t3)
  6. println(t4) //List(11,22,33,44,55,66,77,88,99)
  7. }

案例:利用偏函数筛选元素

collect()

  1. def main(args: Array[String]): Unit = {
  2. val t1 = (1 to 10).toTraversable //底层vector
  3. val t2 = Traversable(1,2,3,4,5,6,7,8,9,10) //底层List
  4. //筛选所有偶数
  5. val pf: PartialFunction[Int, Int] = {
  6. case x if x % 2 == 0 => x
  7. }
  8. val t3 = t1.collect(pf)
  9. // 合并
  10. val t4 = t2.collect({
  11. case x if x % 2 == 0 => x
  12. })
  13. // t3: Vector(2,4,6,8,10)
  14. // t4: List(2,4,6,8,10)
  15. }

案例:计算阶乘

def scan[B](z: B)(op: (B, B) => B)
B是返回类型,z是初始化值, op是具体运算函数
scan()方法等价于scanLeft方法 相反的 scanRight()

  1. val t1 = Traversable(1,2,3,4,5)
  2. val t2 = t1.scan(1)((x: Int, y: Int) => x * y)
  3. x: 前一个值的阶乘值 1 1 2 6 24 120
  4. y: 表示要计算的下一个数据 1 2 3 4 5
  5. val t3 = t1.scan(2)(_ * _)

案例:获取集合指定元素

head: 获取第一个
last: 获取最后一个
headOption: 获取第一个,返回Option

find: 查找满足条件第一个元素
slice: 截取集合的一部分元素

  1. val t1 = Traversable(1,2,3,4,5,6)
  2. println(t1.head)
  3. println(t2.headOption)
  4. println(t3.find(_ % 2 == 0)) //找到第一个偶数
  5. t1.slice(2,5) //包左不包右 List(3, 4, 5)

案例: 元素是否合法

forall() 如果集合中的所有元素都满足指定条件,则返回true, 否则返回false
exists()只要有一个满足,就返回true

  1. val t1 = Traversable(1,2,3,4,5,6)
  2. t1.forall(_ % 2 == 0)//所有元素都是偶数 false
  3. t1.exists(_ % 2 == 0) // 有一个是偶数 true
  4. // filter方法用来过滤
  5. val t2 = t1.filter(_ % 2 != 0)//返回的是集合
  6. t2.size == 0 // false

案例: 聚合函数

  • count:获取满足条件个数
  • sum
  • product : 获取所有元素乘积
  • max
  • min

    1. val t1 = Traversable(1,2,3,4,5,6)
    2. println(t1.count(_ % 2 != 0)) //奇数个数
    3. println(t1.product) // 720

    案例: 集合类型转换

    1. val t1 = (1 to 5).toTraversable
    2. val arr = t1.toArray // 这个输出的是数组的地址值!!!
    3. val list = t1.toList // 输出的是列表
    4. val set = t1.toSet // 输出的是集

    案例: 填充元素

  • fill(): 快速生成指定数量的元素

  • iterate(): 根据条件生成指定个数元素
  • range()方法:生成某个区间内指定间隔的所有数据 ```scala Traversable.fill(5)(“xxx”) //5是元素个数,xxx是填充内容 List(“xxx”,”xxx”,”xxx”,”xxx”,”xxx”) Traversable.fill(3)(Random.nextInt(100)) //包含三个随机数 Traversable.fill(3, 2)(“x”) // List(List(“x”,”x”), List(“x”,”x”), List(“x”,”x”))

Traversable.iterate(1,5)( * 10) // 1是初始值,5是获取元素个数,*10是规则 1 10 100 1000 10000

Traversable.range(1, 21, 5) //包左不包右 5是间隔 不写默认是1 1, 6, 11, 16

  1. <a name="MyY8D"></a>
  2. #### 案例:随机学生序列
  3. ```scala
  4. case class Student(name: String, age: Int)
  5. def main(args: Array[String]): Unit = {
  6. val names: List[String] = List("张三", "李四", "王五")
  7. val r: Random = new Random()
  8. val t1: Traversable[Student] = Traversable.fill(3)(new Student(names(r.nextInt(names.size)), r.nextInt(10) + 20)) //年龄范围20~30
  9. val t2: List[Student] = t1.toList
  10. // 按年龄降序排列
  11. val sortList: List[Student] = t2.sortBy(_.age).reverse
  12. val sortList = t2.sortWith(_.age > _.age)
  13. }

序列Seq

Seq特质代表按序排列的元素序列,特点是有序(存取顺序一致),可重复,有索引

  1. val seq = (1 to 5).toSeq // Range(1,2,3,4,5)

获取长度和元素

  1. val seq = (1 to 5).toSeq
  2. println(seq.length, seq.size)
  3. println(seq(3))
  4. println(seq.apply(3))

获取索引值

indexOf(): 获取元素在列表中第一次出现的位置
lastIndexOf: 获取指定元素在列表中最后一次出现的位置
indexWhere: 获取满足条件的元素,在集合中第一次出现的索引
lastIndexWhere: 获取满足条件的元素,在集合中最后一次出现的索引
indexOfSlice: 获取指定的子序列在集合中第一次出现的位置

  1. val s1 = Seq(1,2,4,6,4,3,2)
  2. println(s1.indexOf(2)) //1
  3. println(s1.lastIndexOf(2)) //6
  4. //第一个参数:查找规则, 第二个参数:索引开始位置
  5. println(s1.indexWhere(x => x < 5 && x% 2 == 0, 2)) //1
  6. println(s1.LastIndexWhere(x => x < 5 && x% 2 == 0)) //6
  7. println(s1.indexOfSlice(Seq(1,2))) //0
  8. println(s1.indexOfSlce(Seq(1,2),3)) //null

判断是否包含指定数据

  • startsWith: 判断是否以指定子序列开头
  • endsWith: 判断集合是否以指定序列结尾
  • contains: 判断是否包含某个指定的数据
  • containsSlice: 判断是否包含某个指定的子序列 ```scala val s1 = (1 to 10).toSeq println(s1.startsWith(Seq(1, 2)))//true println(s1.endWith(Seq(9, 10))) // true

println(s1.contains(3)) //true println(s1.containsSlice(Seq(1,30))) // false

  1. <a name="UQGaM"></a>
  2. #### 修改指定元素
  3. - updated: 修改指定索引位置的元素为指定的值
  4. - patch: 修改指定区间元素为指定的值
  5. ```scala
  6. val s1 = (1 to 5).toSeq
  7. val s2 = s1.updated(2, 10) //2: 修改位置 10:修改后的参数 1,2,10,4,5
  8. val s3 = s1.patch(1, Seq(10, 20), 3) // 3:替换几个元素 修改后的参数:1, 10 , 20, 5

数组

不可变数组

  1. // 1. 创建数组
  2. val arr: Array[Int] = new Array[Int](5)
  3. // 另一种创建方式
  4. val arr2 = Array(22,33,44) // 调用了apply方法 Array.apply(22,33,44)
  5. // 2. 访问元素
  6. println(arr(0)) //0 arr.apply(0)
  7. println(arr(1)) //0
  8. println(arr(2)) //0
  9. arr(0) = 12 // 转换为 arr.update(0, 12)
  10. println(arr(0)) //12
  11. // 3. 数组的遍历
  12. // 普通for循环
  13. for (i <- 0 until arr.length) {
  14. println(arr(i))
  15. }
  16. for (i <- arr.indices) println(arr(i))
  17. // 增强for循环,直接遍历元素
  18. for (elem <- arry2) println(elem)
  19. // 迭代器
  20. val iter = arr2.iterator
  21. while (iter.hasNext)
  22. println(iter.next())
  23. // 调用foreach方法
  24. arr2.foreach( (elemL int) => println(elem) )
  25. arr2.foreach(println)
  26. println(arr2.mkString("--")) //以--分割

变长数组

  1. import scala.collection.mutable.ArrayBuffer
  2. // 定义一个长度为0 的变长数组
  3. val arr1 = ArrayBuffer[Int]()
  4. val arr2 = ArrayBuffer("hadoop", "storm", "spark")
  5. arr2 += "flume" //增加元素
  6. arr2 -= "hadoop" //删除元素
  7. // 将一个包含多个元素的数组,追加到变长数组中
  8. arr2 ++= Array("hive", "sqoop")
  9. arr2 --= Array("sqoop", "spark")
  10. println(arr2)

数组工具

  1. val arr1 = Array(4, 1, 5, 6, 3)
  2. //求和
  3. println(s"sum: ${arr1.sum}")
  4. //最大值
  5. arr1.max
  6. //最小值
  7. arr2.min
  8. //排序升序
  9. val arr2 = arr1.sorted
  10. //反转
  11. val arr3 = arr1.reverse
  12. // 降序:先升序排再反转

元组

元组用来存储多个不同类型的值,例如同时存储姓名、年龄、性别等。元组元素和长度不可变

  • 格式一:val 元组 = (元素1, 元素2,元素3……)
  • 格式二:val 元组 = 元素1 -> 元素2 只适用于元组中两个元素的情况

    访问元组中的元素

    ```scala val tuple1 = “zhangsan” -> “male”

// 方式一 拖过 _编号 获取,第一个元素从1开始 println(tuple1._1) println(tuple1._2)

// 方式二 通过迭代器 val it = tuple1.productIterator for(i <- it) println(i)

  1. <a name="D2gs0"></a>
  2. ## 列表
  3. 特点:有序(存入和取出顺序一样)可重复<br />分为不可变列表和可变列表
  4. <a name="QHzJ7"></a>
  5. ### 不可变列表
  6. 列表元素、长度都是不可变的
  7. ```scala
  8. // 方式一
  9. val list1 = List(1, 2, 3, 4)
  10. // 方式二 :不可变的空列表
  11. val list2 = Nil
  12. // 方式三
  13. val list3 = -1 :: -2 :: Nil

可变列表

  1. import scala.collection.mutable.ListBuffer
  2. // 可变集合都在mutable中不可变再immutable包中(默认导入)
  3. val list1 = ListBuffer[Int]()
  4. val list2 = ListBuffer(1, 2, 3, 4)
  5. list1(0) = 3 //修改元素
  6. list2 += 4 //添加元素
  7. list2 ++= List(2,4,6) // 追加列表
  8. list -= 3 // 删除元素
  9. list --= List(2,4)
  10. val list3 = list2.toList // 变为不可变列表
  11. val arr = list2.toArray //

列表常用操作

基础操作

  1. val list1 = List(1, 2, 3, 4)
  2. val list2 = List(4, 5, 6)
  3. // 判空
  4. println(list1.isEmpty()) //false
  5. // 拼接返回新的列表
  6. val list3 = list1 ++ list2
  7. // 获取首个元素
  8. println(list1.head) //1
  9. // 获取除首个元素外的其它所有元素
  10. println(list1.tail) // List(2, 3, 4)
  11. // 对列表进行反转,返回一个新的
  12. println(list1.reverse) //List(4, 3, 2, 1)
  13. // 获取列表中的前缀元素 表示前三个是前缀
  14. println(list1.take(3)) //List(1,2,3)
  15. // 获取后缀元素 表示前三个是前缀
  16. println(list1.drop(3)) // List(4)

扁平化

将嵌套列表的元素单独放到新列表中

  1. val list1 = List(List(1, 2), List(3), List(4, 5))
  2. val list2 = list1.flatten // 转变为了List(1,2,3,4,5)

拉链与拉开

  • 拉链:将两个列表组合成一个元素为元组的列表
  • 拉开:将一个包含元组的列表,拆解成包含两个列表的元组 ```scala val names = List(“张三”, “李四”, “王五”) val ages = List(23, 24, 25) // 拉链操作 val list1 = names.zip(ages) // List((“张三”,23), (“李四”,24), (“王五”,25)) // 拉开 val tuple1 = list1.unzip // (List(“张三”, “李四”, “王五”), List(23, 24, 25))
  1. <a name="2TSVm"></a>
  2. #### 列表转字符串
  3. ```scala
  4. val list1 = List(1, 2, 3, 4)
  5. println(list1.toString) // List(1, 2, 3, 4)
  6. println(list1) // 可省略,默认调用对象的toString方法
  7. println(list1.mkString(":")) // 1:2:3:4 用指定符号分隔

并集、交集、差集

  1. val list1 = List(1, 2, 3, 4)
  2. val list2 = List(3, 4, 5, 6)
  3. // 并集
  4. val unionList = list1.union(list2) // 1,2,3,4,3,4,5,6
  5. val distinctList = unionList.distinct //去重 1, 2, 3, 4, 5, 6
  6. // 交集
  7. val intersectList = list1.intersect(list2) // 3,4
  8. // 差集
  9. val diffList = list1.diff(list2) // 1, 2

Stack

先进后出,immutable.Stack已经被弃用了,最常用的还是可变栈mutable.Stack, mutable.ArrayStack

  • top获取栈顶元素
  • push入栈操作
  • pop出栈操作
  • clear移除集合所有元素
    1. immutable.Stack独有方法pushAll()把多个元素压入栈
    2. mutable.ArrayStack独有方法:
      1. dup复制栈顶元素
      2. preserving:执行一个表达式,执行完毕后恢复栈,即回到调用前

Stack可变栈

  1. val s1 = mutable.Stack(1,2,3,4,5)
  2. println(s1) // Stack(1,2,3,4,5) Scala从后往前添加,栈顶元素是1
  3. println(s1.top) //1
  4. println(s1.push(6)) // Stack(6,1,2,3,4,5)
  5. println(s1.pushAll(Seq(11,22,33))) // 33,22,11,6,1,2,3,4,5
  6. println(s1.pop()) //33
  7. println(s1.clear) //Stack()

ArrayStack可变栈

  1. val s1 = mutable.ArrayStack(1, 2, 3, 4, 5)
  2. println(s1) // ArrayStack(1, 2, 3, 4, 5)
  3. s1.dup()
  4. println(s1) // ArrayStack(1, 1, 2, 3, 4, 5)
  5. // 实现先情况集合元素,再回复集合中清除的数据
  6. s1.presercing({
  7. s1.clear()
  8. println("执行了吗")
  9. })
  10. println(s1) // 执行了吗 ArrayStack(1, 1, 2, 3, 4, 5)

Queue

队列先进先出

  • enqueue入队方法,可以传零到多个元素
  • dequeue出队列, 移除一个元素
  • dequeueAll移除所有满足条件元素
  • dequeueFirst移除第一个满足条件元素
    1. val q1 = mutable.Queue(1, 2, 3, 4, 5)
    2. q1.enqueue(6)
    3. q1.enqueue(7,8,9)
    4. println(q1) // Queue(1,2,3,4,5,6,7,8,9)
    5. println(q1.dequeue()) //1
    6. println(q1.dequeueFirst(_ % 2 != 0)) //Some(3)
    7. println(q1.dequeueAll(_ % 2 == 0)) //ArrayBuffer(2,4,6,8)
    8. println(q1) // Queue(5,7,9)

集Set

Set代表没有重复的集合,唯一、无序
默认不可变集

  • HashSet前缀树,元素唯一,无序
  • LinkedHashSet唯一,有序
  • TreeSet唯一,排序
    1. val s1 = SortedSet(1, 4, 3, 2, 5)
    2. println(s1) // TreeSet(1,2,3,4,5)
    3. val s2 = mutable.HashSet(1, 4, 3, 2, 5)
    4. println(s2) // Set(1,5,2,3,4)
    5. val s3 = mutable.LinkedHashSet(1, 4, 3, 2, 5)
    6. println(s3) // Set(1,4,3,2,5)

    不可变集

    创建不可变集

    ```scala val set1 = SetInt

val set2 = Set(1, 1, 3, 2, 4)

println(s”set1: $set1”) // set1: Set() println(s”set2: $set2”) // set2: Set(1, 4, 3, 2) 无序 不重复

  1. <a name="RYTrD"></a>
  2. #### 不可变集的常见操作
  3. ```scala
  4. val set1 = Set(1,1,2,3,4,5)
  5. // 获取大小
  6. println(set1.size) //5 删掉了一个1
  7. //遍历集
  8. for(i <- set1) println(i)
  9. // 删除元素1
  10. println(set1 - 1) // 5,2,3,4
  11. // 拼接另一个集
  12. val set3 = set1 ++ Set(6, 7, 8)
  13. println(set3) // 5,1,6,2,7,3,8,4
  14. // 拼接列表
  15. val set4 = set1 ++ List(6,7,8,9)
  16. println(set4) // 5,1,6,9,2,7,3,8,4

可变集

元素、集长度都可变

  1. import scala.collection.mutable.Set
  2. val set1 = Set(1, 2, 3, 4)
  3. set1 += 5
  4. set1 ++= List(6,7,8)
  5. set1 -= 1
  6. set1 --= List(3,5,7)
  7. println(set1)

映射Map

Map,键值对组成的集合,键具有唯一性,但值可重复
默认是不可变map

  1. val map = Map("A" -> 1, "B" -> 2, "C" -> 3)
  2. for((k, v) <- map) println(k, v)
  3. map.foreach(println(_))
  4. println(map.filterKeys(_ == "B")

不可变Map

不可变Map指元素长度都不可变

  • val map = Map(键->值, 键->值, 键->值, 键->值)
  • val map = Map((键,值),(键,值),(键,值)) 不推荐
    1. val map1 = Map("张三" -> 23, "李四" -> 24, "李四" -> 40) // 40就被覆盖了

    可变Map

    ```scala import scala.collection.mutable.Map

val map1 = Map(“张三” -> 23, “李四” -> 24)

map1(“张三”) = 30

  1. <a name="NJKnO"></a>
  2. ### Map基本操作
  3. ```scala
  4. val map1 = Map("张三" -> 23, "李四" -> 24)
  5. // 通过键查找值
  6. println(map1("张三")) // 23
  7. // 获取所有键
  8. println(map1.keys) // "张三" "李四"
  9. //获取所有值
  10. println(map1.values) //
  11. //遍历
  12. for((k, v) <- map1) println(k,v)
  13. // 通过键获取一个值,如果键不存在,返回一个值
  14. println(map1.getOrElse("王五",-1))
  15. // 增加一组数据(不可变)
  16. val map2 = map1 + "王五" -> 25
  17. //增加一组数据(可变)
  18. import scala.collection.mutable.Map
  19. val map3 = mutable.Map("张三" -> 23, "李四" -> 24)
  20. map3 += "王五" -> 25
  21. =//删除一组数据(可变)
  22. map3 -= "王五"

迭代器

Scala对每一类集合都提供了迭代器
Iterable代表一个可迭代的集合,继承自Traversable特质,是其它集合的父特质,获得了iterator方法(抽象方法,需要具体集合类实现)

  • iterator()属于主动迭代,可以通过next(),hasNext()自主控制迭代
  • foreach()属于被动迭代,由集合本身控制 ```scala val list1 = List(1, 2, 3, 4, 5)

// 使用迭代器遍历 val it:Iterator[Int] = list1.iterator while(it.hasNext) { println(it.next()) } //迭代器已经迭代完毕 println(it.next()) // NoSuchElementException

//foreach遍历 //list1.foreach((x:Int)=>println(x)) list1.foreach(println(_))

  1. <a name="fHHo4"></a>
  2. #### 案例:分组遍历
  3. def grouped(size: Int): Iterator[Iterable[A]]
  4. ```scala
  5. val list = (1 to 13).toIterable
  6. val it = list.grouped(5)
  7. val b1 = it.hasNext
  8. if(b1) {
  9. val result1 = it.next()
  10. println(b1, result1) // (true, Vector(1, 2, 3, 4, 5))
  11. }
  12. val b2 = it.hasNext
  13. if(b2) {
  14. val result1 = it.next()
  15. println(b1, result1) // (true, Vector(6,7,8,9,10))
  16. }
  17. val b3 = it.hasNext
  18. if(b3) {
  19. val result1 = it.next()
  20. println(b1, result1) // (true, Vector(11,12,13))
  21. }
  22. val b4 = it.hasNext
  23. val result1 = it.next() //NoSuchElementException
  24. // 合并
  25. while(it.hasNext) {
  26. val result = it.next()
  27. println(result)
  28. }

案例:按照索引生成元组

zipWithIndex()

  1. val list1 = Iterable("A","B","C","D","E")
  2. val list2: Iterable[(String, Int)] = list1.zipWithIndex //List((A,0),(B,1),(C,2),(D,3),(E,4))
  3. val list3: Iterable[(Int, String)] = list2.map(x => x._2 -> x._1)
  4. list3.foreach(println(_))

案例: 判断集合是否相同

sameElements() 判断集合中元素及元素迭代顺序是否一致

  1. val list1 = Iterable("A","B","C")
  2. println(list1.sameElements(Iterable("A","C","B"))) // false
  3. val hs = HashSet(1, 2)
  4. val ts = TreeSet(2, 1) // TreeSet会默认升序
  5. println(hs.sameElements(ts)) //true

集合相关函数

遍历(foreach)

def foreach(f:(A) => Unit): Unit

  1. val list1 = List(1, 2, 3, 4)
  2. list1.foreach((x: Int) => {println(x)})

简化函数定义

  1. 通过类型推断简化函数

list1.foreach(x => println(x))

  1. 通过下划线简化函数

函数参数只在函数体中出现一次,且没有复杂使用
list1.foreach(println(_))

映射(map)

集合映射操作时将一种数据类型转换为另一种类型的过程
def map[B](f: (A) => B): TraversableOnce[B]

  1. val list1 = List(1, 2, 3, 4)
  2. // 将对应的数字转换为*个数
  3. val list2 = list1.map((x: Int) => {"*" * x})
  4. //类型推断
  5. val list3 = list1.map(a => "*" * a)
  6. // 下划线
  7. val list4 = list1.map("*" * _)
  8. println(list2)
  9. // List(*, **, ***, ****)

扁平化映射(flatMap)

扁平化映射可以理解为先map,然后flatten
def flatMap[B](f:(A) => GenTraversableOnce[B]): TraversableOnce[B]

  1. // 有一个长字符串列表,获取文本中的每一个单词,并将每一个单词放到列表中
  2. val list1 = List("hadoop hive spark flink flume", "kudu hbase sqoop storm")
  3. // 方式一
  4. val list2 = list1.map((x:String) => {x.split(" ")}) // 将每一个元素,按空格分割成数组
  5. // List(Array("hadoop",hive","spark","flink","flume"), Array(....))
  6. val list3 = list2.flatten
  7. // List("hadoop","hive",...)
  8. // 方式二 直接实现
  9. val list4 = list1.flatMap((x:String) => {x.split(" ")})
  10. val list5 = list1.flatMap(_.split(" "))

过滤

过滤出符合一定条件的元素
def filter(f:(A) => Boolean): TraversableOnce[A]

  1. val list1 = (1 to 9).toList
  2. // 过滤出所有偶数
  3. val list2 = list1.filter(x => x % 2 == 0)
  4. val list3 = list1.filter(_ % 2 == 0)

排序

默认排序(sorted)

升序排列,降序通过升序后reverse实现

  1. val list1 = List(3, 1, 2, 9, 7)
  2. val list2 = list1.sorted
  3. val list3 = list2.reverse

指定字段排序

列表元素根据传入的函数转换后,再进行排序(升序)
def sortBy[B](f:(A)=>B): List[A]

  1. val list1 = List("01 hadoop", "02 flume", "03 hive", "04 spark")
  2. val list2 = list1.sortBy(x => x.split(" ")(1))
  3. // x.split(" ")表示 Array("01", "hadoop"), Array("02","flume")...
  4. // x.split(" ")(1)表示每个数组中第二个元素 "hadoop" "flume" ...
  5. println(list2) //List(02 flume, 01 hadoop", 03 hive", 04 spark)

自定义排序

根据自定义函数规则进行排序
传入一个比较大小的函数对象,接受两个集合类型的元素参数,返回两个元素大小,小于返回true,大于返回false
def sortWith(f: (A, A) => Boolean): List[A]

  1. val list1 = List(2,3,1,6,5,4)
  2. // 降序排列
  3. val list2 = list1.sortWith((x, y) => x > y)
  4. val list2 = list1.sortWith(_ > _)
  5. println(s"list2: ${list2}")
  6. // List(6, 5, 4, 3, 2, 1)

分组

  1. val list1 = List("刘德华"->"男", "刘亦菲"->"女","hqw"->"男")
  2. //安照性别分组
  3. val map1 = list1.groupBy(x => x._2)
  4. // 优化成这样val map1 = list1.groupBy(_._2)
  5. // Map("男" -> List(刘德华"->"男","hqw"->"男"), "女" -> List("刘亦菲"->"女"))
  6. //统计不同性别的学生人数
  7. val map2 = map1.map(x => x._1 -> x._2.size)

聚合

  1. val list1 = (1 to 10).toList
  2. val list2 = list1.reduce(_ + _) // (x,y)=>x+y
  3. val list3 = list1.reduceLeft(_ + _) //从左往右
  4. val list4 = list1.reduceRight(_ + _) //从右往左
  5. val list5 = list1.reduceRight(_ - _)
  6. /*
  7. 第一次:9 - 10 = -1
  8. 第二次:8 - -1 = 9
  9. ...
  10. */

案例:学生成绩

  1. object test {
  2. def main(args: Array[String]): Unit = {
  3. // 定义列表
  4. val stuList = List(("张三", 34, 22, 44),("李四",22,44,55),("王五", 44, 55, 66))
  5. // 获取语文成绩60以上的学生
  6. val chineseLise = stuList.filter(x => x._2 >= 60)
  7. // 获取总成绩
  8. val countList = stuList.map(x => x._1 -> (x._2 + x._3 + x._4))
  9. // 按总成绩排列
  10. val sortList = countList.sortWith((x, y) => x._2 > y._2)

案例: 统计字符个数

  1. println("请录入字符串:")
  2. val str = StdIn.readLine()
  3. val map = mutable.Map[Char, Int]()
  4. //转为字符数组
  5. val chs = str.toCharArray
  6. for (k <- chs) {
  7. if (!map.contains(k)) {
  8. // 如果字符第一次出现,将其记录为1
  9. map += (k -> 1)
  10. } else {
  11. map += (k -> (map.getOrElse(k, 1) + 1))
  12. }
  13. }
  14. map.foreach(println(_))