Scala集合(二)
将函数映射到集合
map方法
val names = List("Peter" , "Paul", "Mary")
names.map(_.toUpperCase) // 等同于 for(n <- names) yield n.toUpperCase
flatMap方法,如果函数产出一个集合,又想将所有值串联在一起
def ulcase(s:String) = Vector(s.toUpperCase(), s.toLowerCase())
names.map(ulcase)得到
List(Vector("PETER","peter"), Vector("PAUL","paul"), Vector("MARY","mary"))
names.flatMap(ulcase)得到
List("PETER","peter","PAUL","paul","MARY","mary")
collect 方法用于 partial function,那些并没有对所有可能的输入值进行定义的函数, 产出被定义的所有参数的函数值得集合
"-3+4".collect(case '+' -> ; case '-' -> -) // vector(-1,1)
foreach方法
names.foreach(println)
化简、折叠和扫描
List(,,,).reduceLeft(_ - _)
( ( - ) - ) - = - - - = -
List(,,,).reduceRight(_ - _)
- ( - ( - ) ) = - + - = -
以不同首元素开始计算
List(,,,).foldLeft()(_ - _)
---- = -
List(,,,).foldLeft(" ")(_ + _) // 由柯里化判断第二个参数类型定义(String, Int) => String
" " + + ++ = ""
( /: List(,,,))(_ - _) // /: 操作符代替了foldLeft操作
Scala 也提供了foldRight 和 :\的变体
折叠有时可以代替循环,比如计算字母出现频率
val freq = scala.collection.mutable.Map[Char, Int]() // 可变映射
for( c <- "Mississippi")
freq(c) =freq.getOrElse(c,)+ // Map('i' ->4, 'M' -> 1, 's' -> 4, 'p' ->2)
折叠实现
(Map[Char, Int]() /:"Mississippi"){
(m,c) => m + (c -> (m.getOrElse(c,) +)
}// 这里的 Map是不可变,每次计算出一个新的Map
scanLeft,scanRight, 得到包含所有中间结果的集合
( to ).scanLeft()(_ + _)
Vector(,,,,,,,,,,)
拉链操作
zip
val prices = List(5.0,20.0,9.95) // 价格
val quantities = List(,,) //数量
prices zip quantities 得到一个List[(Double, Int)] , 一个个对偶的列表
List[(Double, Int)] = List( (5.0, ), (20.0, ), (9.95, ))
计算总价
((prices zip quantities) map {p => p._1 * p._2}) sum
如果两个集合数量不一致
List( 5.0, 20.0, 9.95 ) zip List(, ) // List((5.0, 10), (20.0, 2))
zipAll 指定短列表的缺省值:第二个参数补充左边,第三个参数补充右边
List(,).zipAll(List(),,) // List((1,2),(1,7))
List().zipAll(List(,),,)// List((1,2), (3,6))
zipWithIndex, 返回对偶列表,第二个组成部分是元素下标
"Scala".zipWithIndex // Vector(('S',0),('c',1),('a',2),('l',3),('a',4))
求最大编码的值得下标为
"Scala".zipWithIndex.max._2
迭代器 (相对于集合而言是一个“懒”的替代品,只有在需要时才去取元素,如果不需要更多元素,不会付出计算剩余元素的代价)
对于那些完整构造需要很大开销的集合,适合用迭代器 如Source.fromFile产出一个迭代器,因为整个文件加载进内存不高效。 迭代器的两种用法 while(iter.hasNext) iter.next() for(elem <- iter) 对elem操作 上述两种循环都会讲迭代器移动到集合末端,不能再被使用, 调用 map filter count sum length方法后, 迭代器也会位于集合的末端,不能使用 find 或 take ,迭代器位于找到的元素之后
流(stream)
迭代器每次调用next都会改变指向,
如果要缓存之前的值,可以使用流
流是一个尾部被懒计算的不可变列表,也就是说只有需要时才计算
def numsForm(n:BigInt) : Stream[BigInt] = n #:: numsForm(n+) // #:: 操作符 构建出来的是一个流
var tenOrMore = numsForm() // Stream(10,?), 其尾部是未被求值得
tenOrMore.tail.tail.tail // Stream(13,?)
val squares = numsForm().map{ x=> x*x) // Stream(1,?)
take 可以一次获得多个值, force强制求值
squares.take().force // Stream(1,4,9,16,25)
squares.force // 会尝试对一个无穷流的所有成员求值,最后OutOfMemoryError
迭代器可以用来构造一个流
Source.getLines返回一个Iterator[String],用这个迭代器,对于每一行只能访问一次,而流将缓存访问过的行,允许重新访问
val words = Sourcce.fromFile("/usr/share/dict/words").getLines.toStream
words // Stream(A, ?)
words() // Aachen
words // Stream(A, A'o, AOL, AOL's, Aachen, ?)
懒视图(应用于集合)
类似流的懒理念 与流的不同 、连第一个元素都不会求值 、不会缓存求过的值 val powers = ( unti ).view.map(pow(,_)) powers() // pow(10,100)被计算,其他值未计算,同时也不缓存,下次pow(10,100)将重新计算 force方法可以对懒视图强制求值,得到与原集合相同类型的新集合, 懒视图的好处:可以避免在多种变换下产生的中间集合 ( to ).map(pow(,_)).map(/_) //先第一个map,再第二个map, 构建了一个中间集合 ( to ).view.map(pow(,_)).map(/_).force // 记住两个map操作,每个元素被两个操作同时执行,不需要额外构中间集合
与Java集合的互操作
import scala.collection.JavaConversions._
val props:scala.collection.mutable.Map[String,String] = System.getProperties()
如果担心那些不需要的隐式转换也被引入的话,只引入需要的即可
import scala.collection.JavaConversions.propertiesAsScalaMap
这些转换产出的是包装器,让你可以使用目标接口来访问原本的值
props("name") = "clat" //props既是包装器
包装器将调用底层Properties对象的put("name","clat")

线程安全的集合
Scala类库提供了六个特质,将他们混入集合,让集合的操作变成同步 SynchromizedBuffer SynchromizedMap SynchromizedPriorityQueue SynchromizedQueue SynchromizedSet SynchromizedStack val scores =new scala.collection.collection.mutable.HashMap[String, Int] with scala.collection.mutalbe.SynchronizzedMap[String,Int] 注:这里可以确保scores不会被破坏,任何操作都必须先完成,其他线程才可执行另一个操作。但并发修改和遍历集合并不安全。 通常来说,最好使用java.util.concurrent包中的类.
并行集合
为了更好利用计算机的多个处理器,支持并发通常是必需的 如果coll是个大型集合,那么 coll.par.sum //并发求和,par方法产出当前集合的一个并行实现,该实现会尽可能地并行执行集合方法 coll.par.count(_ % ==) //计算偶数的数量 对数组、缓冲、哈希表、平衡树而言,并行实现会直接重用底层实际集合的实现,所以很高效。 可以通过对要遍历的集合应用.par并行化for循环 for( i <- ( until ).par) print( i + " " ) //数字是按照作用于该任务的线程产出的顺序输出 在for/yield循环中,结果是依次组装的 for( i <- ( until ).par) yield i +" " par返回的并行集合扩展自ParSeq ParSet Parmap,都是ParIterable的子类型,不是Iterable的子类型,所以不能将并行集合传递给预期Iterable Seq Set Map的方法。 可以用ser方法将并行集合转换回串行的版本。
只有可以自由结合的操作 可以用平行集合 (a op b) op c = a op( b op c), 加是可自由结合的 (a -b ) -c != a - (b -c) 减法不是自由结合 有一个fold方法对集合的不同部分进行操作,但是不像foldLeft和foldRight那样灵活, 该操作符的两个操作元都必须是集合的元素类型,要求fold的参数类型与集合元素一样,不像上面foldLeft,参数是String, 集合是Int 那样 coll.par.fold()(_ + _) aggregate方法,可以解决上面的问题,该操作符应用于集合的不同部分,然后再用你另一个操作符组合结果 str.par.aggregate(Set[Char]())(_ + _, _ ++ _) //等同于 str.foldLeft(Set[Char]())(_ + _) 产出一个str中所有不同字符的集
Scala集合(二)的更多相关文章
- Scala集合类型详解
Scala集合 Scala提供了一套很好的集合实现,提供了一些集合类型的抽象. Scala 集合分为可变的和不可变的集合. 可变集合可以在适当的地方被更新或扩展.这意味着你可以修改,添加,移除一个集合 ...
- Scala学习(二)--- 控制结构和函数
控制结构和函数 摘要: 本篇主要学习在Scala中使用条件表达式.循环和函数,你会看到Scala和其他编程语言之间一个根本性的差异.在Java或C++中,我们把表达式(比如3+4)和语句(比如if语句 ...
- Scala函数式编程(三) scala集合和函数
前情提要: scala函数式编程(二) scala基础语法介绍 scala函数式编程(二) scala基础语法介绍 前面已经稍微介绍了scala的常用语法以及面向对象的一些简要知识,这次是补充上一章的 ...
- Scala集合操作
大数据技术是数据的集合以及对数据集合的操作技术的统称,具体来说: 1.数据集合:会涉及数据的搜集.存储等,搜集会有很多技术,存储技术现在比较经典方案是使用Hadoop,不过也很多方案采用Kafka. ...
- Spark:scala集合转化为DS/DF
scala集合转化为DS/DF case class TestPerson(name: String, age: Long, salary: Double) val tom = TestPerson( ...
- Scala集合常用方法解析
Java 集合 : 数据的容器,可以在内部容纳数据 List : 有序,可重复的 Set : 无序,不可重复 Map : 无序,存储K-V键值对,key不可重复 scala 集合 : 可变集合( ...
- Scala集合笔记
Scala的集合框架类比Java提供了更多的一些方便的api,使得使用scala编程时代码变得非常精简,尤其是在Spark中,很多功能都是由scala的这些api构成的,所以,了解这些方法的使用,将更 ...
- Scala集合(一)
Scala集合的主要特质 Iterator,用来访问集合中所有元素 val coll = ... // 某种Iterable val iter = col.iterator while(iter.ha ...
- 再谈Scala集合
集合!集合!一个现代语言平台上的程序员每天代码里用的最多的大概就是该语言上的集合类了,Scala的集合丰富而强大,至今无出其右者,所以这次再回过头再梳理一下. 本文原文出处: 还是先上张图吧,这是我 ...
随机推荐
- Kubernetes部署SpringCloud(二) 部署ZUUL与服务 非host, 伸缩与负载均衡
因为服务需要可缩容,所以不能使用host部署. 涉及两个应用,zuul,basic-info-api 验证,在k8s任意一个node 从zuul 访问 basic-info-api 创建一个Sprin ...
- day_6.6 py
Tftp 下载器演示 2018-6-6 14:11:09 #!/usr/bin/env python #!--*--coding:utf-8 --*-- #!@Time :2018/6/6 11:55 ...
- 【JavaScript】--- ES6/ES7/ES8
一.async async其实是ES7才有有的关键字,async的意思是异步,顾名思义是有关异步的操作 async用于声明一个函数是异步的. 通常情况下async.await都是跟随promise一起 ...
- 安装和配置hive
1.上传hive.mysql.mysql driver到服务器/mnt目录下: [root@chavin mnt]# ll mysql-5.6.24-linux-glibc2.5-x86_64.tar ...
- Django:模板template(一)
把模板的过程.语法.标签.反向地址解析.过滤器.模板继承与HTML转义记下笔记 1.概述及demo 动态生成HTML 模板的设计实现业务逻辑(View)和显示内容(template)的分离 一个模板可 ...
- C和C指针小记(九)-指针用法1
1. *p++ 最常用的一个指针的用法,就是在循环中用来迭代. *p++ 共有3步操作: 1.++操作符把p所指向的内存中的值复制一份 2.++操作符把p加1(实际是一个p所指内存单元的大小,这也是编 ...
- HBase实战 | 知乎实时数仓架构演进
https://mp.weixin.qq.com/s/hx-q13QteNvtXRpNsE5Y0A 作者 | 知乎数据工程团队编辑 | VincentAI 前线导读:“数据智能” (Data Inte ...
- xcode工程编译错误:"An instance 0xca90200 of class UITableView was deallocated while key value observers were still registered with it"
An instance 0xca90200 of class UITableView was deallocated while key value observers were still regi ...
- [hyperscan][pkg-config] hyperscan 从0到1路线图
经过一系列的研究学习,知识储备之后,终于,可以开始研究hyperscan了. [knowledge][模式匹配] 字符匹配/模式匹配 正则表达式 自动机 [knowledge][perl][pcre] ...
- Interceptor的基本介绍和使用
简介 java里的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action执行前阻止其执行,同时也提供了一种可以提取Act ...