集合应用
map映射操作
将集合中的每一个元素通过指定功能(函数)映射(转换)成新的结果集合。
相当于def map[泛型](f: (A) ⇒ B): HashSet[泛型]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vhFuWgEt-1575173838451)(…/…/…/MarkdownPictures/scala/1565874704650.png)]
flatmap映射
flat即压扁 将集合中的每个元素的子元素映射到某个函数并返回新的集合。
val names = List("Alice", "Bob", "Nick")
def upper( s : String ) : String = {
s. toUpperCase
}
//得到list(A,L,I,C,E,B,O,B,N,I,C,K)
filter集合元素的过滤
filter:将符合要求的数据(筛选)放置到新的集合中,filter()里的函数返回值类型必须是布尔值
val names2 = names.filter(startA) // 如果startA 返回一个true,则加入到新集合中,否则,过滤
fold折叠
fold函数将上一步返回的值作为函数的第一个参数继续传递参与运算,直到list(集合)中的所有元素被遍历。同外部reduce
-
reduceLeft相当于简化版的foldLeft,fold函数传入的参数也可以是引用类型比如对象
-
fold,foldLeft,foldRight 使用同reduce相似
val list = List(1, 2, 3, 4) def minus( num1 : Int, num2 : Int ): Int = { num1 - num2} println(list.foldLeft(5)(minus))//等价对化简 List(5,1,2,3,4)等于minus(minus(minus(minus(5,1),2),3),4)) =-5 println(list.foldRight(5)(minus)) // minus(1,minus(2,minus(3,minus(4,5)))) = 3
-
foldLeft和foldRight 缩写方法分别是:/:和:\
reduce化简
化简:将二元函数引用于集合中的函数 相当于折叠的集合内操作
scala推荐的算法是递归,所以reduce都是两两操作
-
reduceLeft(f) 从左向右化简,接收的函数需要的形式为 op: (B, A) => B): B
val list = List(1, 20, 30, 4, 5) val sum1 = list.reduceLeft(sum1)// 无需输入() def sum1(n1: Int, n2: Int): Int = n1 + n2 //List(1, 20, 30, 4, 5)相当于sum(sum(sum(sum(1, 20), 30), 4),5)
-
reduceRight(f)跟reduceLeft(f)相反 从右往左
-
reduce(f)跟reduceLeft(f)一样
-
reduceByKey
scan扫描
扫描,即对某个集合的所有元素做fold操作,但是会把产生的所有中间结果(包含输入的参数)放置于一个集合(vector)中保存
- 用法 类似fold
- scanRight 传入的都在最右边
def minus( num1 : Int, num2 : Int ) : Int = { num1 - num2}
def add( num1 : Int, num2 : Int ) : Int = {num1 + num2}
val i8 = (1 to 5).scanLeft(5)(minus) //5(1,2,3,4,5) 等价(5, 4, 2,-1,-5,-10)
vector(5, 4, 2,-1,-5,-10)
val i9 = (1 to 5).scanRight(5)(add)
vector(20,19,17,14,10,5)
练习题
课堂练习2
val sentence = “AAAAAAAAAABBBBBBBBCCCCCDDDDDDD”
使用映射集合,统计一句话中,各个字母出现的次数
提示:Map[Char, Int]()
使用scala的flodLeft折叠方式实现
def main(args: Array[String]): Unit = {
val sentence = "AAAAAABBCCDDDDDD"
var map1 = Map[Char, Int]()
val map2 = sentence.foldLeft(map1)(charCount)
println("map2=" + map2)
println("map1=" + map1)
//使用charCount2,生产
var map3 = mutable.Map[Char, Int]()
sentence.foldLeft(map3)(charCount2)
println("map3=" + map3)
}
//说明
//1. map : Map[Char, Int] : 左折叠时传入的第一个参数,返回的类型也是Map[Char, Int]
//2. c : Char, 因为从 "AAAABCC..." 每次取出的元素就是 Char
//3. map + (k -> v) // 如果k 没有就是增加,如果存在,是修改
//4. map.getOrElse(c, 0) + 1 => 统计当前 c 出现的次数
def charCount( map : Map[Char, Int], c : Char ): Map[Char, Int] = {
map + (c -> (map.getOrElse(c, 0) + 1)) //不可变map
}
//使用可变的Map 玩一把
def charCount2(map : mutable.Map[Char, Int], c : Char ): mutable.Map[Char, Int] = {
map += (c -> (map.getOrElse(c, 0) + 1)) //不可变map
}
扩展
拉链
将两个集合进行 对偶元组合并
val list1 = List(1, 2 ,3)
val list2 = List(4, 5, 6)
println(list1.zip(list2)) //List((1,4), (2,5), (3,6))
- 拉链的本质就是两个集合的合并操作,合并后每个元素是一个 对偶元组
- 如果两个集合个数不对应,会造成数据丢失。
- 集合不限于List, 也可以是其它集合比如 Array
- 如果要取出合并后的各个对偶元组的数据,可以按元组方法遍历
for(item<-list3){ print(item._1 + " " + item._2) //取出时,按照元组的方式取出即可 }
迭代器
通过iterator方法从集合获得一个迭代器,通过while循环和for表达式对集合进行遍历
val iterator = List(1, 2, 3, 4, 5).iterator // 得到迭代器
println("--------遍历方式1 -----------------")
while (iterator.hasNext) {
println(iterator.next())
}
println("--------遍历方式2 for -----------------")
val iterator2 = List(11, 22, 33, 44, 55).iterator // 得到迭代器
for(enum <- iterator2) {
println(enum) //
}
- iterator 的构建实际是 AbstractIterator 的一个匿名子类,该子类提供了
def iterator: Iterator[A] = new AbstractIterator[A] {
var these = self
def hasNext: Boolean = !these.isEmpty
def next(): A =
- 该AbstractIterator 子类提供了 hasNext next 等方法.
- 如果需要重新迭代,重新获取迭代器
- 可以使用 while的方式,使用hasNext next 方法变量