集合元素与函数的映射 1)map:将集合中的每一个元素映射到某一个函数 val names = List("Alice", "Bob", "Nick") println(names.map(_.toUpperCase)) |
2) flatmap:flat即压扁,压平,扁平化,效果就是将集合中的每个元素的子元素映射到某个函数并返回新的集合 val names = List("Alice", "Bob", "Nick") println(names.flatMap(_.toUpperCase())) | 5.9 化简、折叠、扫描1) 折叠,化简:将二元函数引用于集合中的函数 val list = List(1, 2, 3, 4, 5) val i1 = list.reduceLeft(_ - _) val i2 = list.reduceRight(_ - _) println(i1) println(i2) |
.reduceLefft(_ - _)这个函数的执行逻辑如图所示: file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image001.png .reduceRight(_ -_)反之同理 2) 折叠,化简:fold fold函数将上一步返回的值作为函数的第一个参数继续传递参与运算,直到list中的所有元素被遍历。可以把reduceLeft看做简化版的foldLeft。相关函数:fold,foldLeft,foldRight,可以参考reduce的相关方法理解。 val list2 = List(1, 9, 2, 8) val i4 = list2.fold(5)((sum, y) => sum + y) println(i4) |
foldRight val list3 = List(1, 9, 2, 8) val i5 = list3.foldRight(100)(_ - _) println(i5) |
尖叫提示:foldLeft和foldRight有一种缩写方法对应分别是:/:和:\ 例如: foldLeft val list4 = List(1, 9, 2, 8) val i6 = (0 /: list4)(_ - _) println(i6) |
3) 统计一句话中,各个文字出现的次数 val sentence = "一首现代诗《笑里藏刀》:哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈刀哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈" //m + (“一” -> 1, “首” -> 1, “哈” -> 1) val i7 = (Map[Char, Int]() /: sentence)((m, c) => m + (c -> (m.getOrElse(c, 0) + 1))) println(i7) |
4) 折叠,化简,扫描 这个理解需要结合上面的知识点,扫描,即对某个集合的所有元素做fold操作,但是会把产生的所有中间结果放置于一个集合中保存。 val i8 = (1 to 10).scanLeft(0)(_ + _) println(i8) | 5.10 拉链 val list1 = List("15837312345", "13737312345", "13811332299") val list2 = List(17, 87) println(i1) | 5.11 迭代器你可以通过iterator方法从集合获得一个迭代器,通过while循环和for表达式对集合进行遍历。 val iterator = List(1, 2, 3, 4, 5).iterator while (iterator.hasNext) { println(iterator.next()) } 或: for(enum <- iterator) { println(enum) } | 5.12 流 Streamstream是一个集合。这个集合,可以用于存放,无穷多个元素,但是这无穷个元素并不会一次性生产出来,而是需要用到多大的区间,就会动态的生产,末尾元素遵循lazy规则。 1) 使用#::得到一个stream def numsForm(n: BigInt) : Stream[BigInt] = n #:: numsForm(n + 1) |
2) 传递一个值,并打印stream集合 val tenOrMore = numsForm(10) println(tenOrMore) |
3) tail的每一次使用,都会动态的向stream集合按照规则生成新的元素 println(tenOrMore.tail) println(tenOrMore) |
4) 使用map映射stream的元素并进行一些计算 println(numsForm(5).map(x => x * x)) | 5.13 视图 ViewStream的懒执行行为,你可以对其他集合应用view方法来得到类似的效果,该方法产出一个其方法总是被懒执行的集合。但是view不会缓存数据,每次都要重新计算。 例如:我们找到10万以内,所有数字倒序排列还是它本身的数字。 val viewSquares = (1 to 100000) .view .map(x => { // println(x) x.toLong * x.toLong }).filter(x => { x.toString == x.toString.reverse }) println(viewSquares(3)) for(x <- viewSquares){ print(x + ",") } | 5.14 线程安全的集合所有线程安全的集合都是以Synchronized开头的集合,例如: SynchronizedBuffer SynchronizedMap SynchronizedPriorityQueue SynchronizedQueue SynchronizedSet SynchronizedStack | 5.15 并行集合Scala为了充分使用多核CPU,提供了并行集合(有别于前面的串行集合),用于多核环境的并行计算。 主要用到的算法有: Divide and conquer : 分治算法,Scala通过splitters,combiners等抽象层来实现,主要原理是将计算工作分解很多任务,分发给一些处理器去完成,并将它们处理结果合并返回 Work stealin:算法,主要用于任务调度负载均衡(load-balancing),通俗点完成自己的所有任务之后,发现其他人还有活没干完,主动(或被安排)帮他人一起干,这样达到尽早干完的目的。 1) 打印1~5 (1 to 5).foreach(println(_)) println() (1 to 5).par.foreach(println(_)) |
2) 查看并行集合中元素访问的线程 val result1 = (0 to 10000).map{case _ => Thread.currentThread.getName}.distinct val result2 = (0 to 10000).par.map{case _ => Thread.currentThread.getName}.distinct println(result1) println(result2) | 5.16 操作符这部分内容没有必要刻意去理解和记忆,语法使用的多了,自然就会产生感觉,该部分内容暂时大致了解一下即可。 1) 如果想在变量名、类名等定义中使用语法关键字(保留字),可以配合反引号反引号: 2) 这种形式叫中置操作符,A操作符B等同于A.操作符(B) 3) 后置操作符,A操作符等同于A.操作符,如果操作符定义的时候不带()则调用时不能加括号 4) 前置操作符,+、-、!、~等操作符A等同于A.unary_操作符 5) 赋值操作符,A操作符=B等同于A=A操作符B
|