快学Scala笔记(四)
来源:互联网 发布:java bufferedreader 编辑:程序博客网 时间:2024/06/05 18:33
十三、集合
主要的集合特质
Seq是有先后顺序的值的序列,如数组或列表
IndexedSeq允许通过下标访问任何元素,比如ArrayBuffer
Set是一组没有先后次序的值,SortedSet中以某种排序过的顺序访问
Map是一组键值对,SortedMap按照键的排序访问其中的实体
每个Scala集合特质或类都有一个带有apply方法的伴生对象,这个apply方法可以用来构建集合中的实例:
Iterable( 0xFF, 0xFF00, 0xFF0000 )
Set( Color.RED, Color.GREEN, Color.BLUE )
Map( Color.RED -> 0xFF0000, Color.GREEN -> 0xFF00 )
SortedSet( “hello”, “world” )
可变和不可变集合
不可变集合可以安全地共享其引用
Scala优先采用不可变集合,总被引入的scala包和Predef对象里有指向不可变特质的类型别名List、Set和Map
序列
Vector是ArrayBuffer的不可变版本:带下标的序列,支持随机访问。
Vector是以树形结构的形式实现的,每个节点可以有不超过32个子节点。
Range表示一个整数序列,Range对象并不存储所有值,而只是起始值、结束值和增值。
列表
Scala中,列表要么是Nil,要么是一个head元素加上一个tail,而tail又是一个列表。
val digits = List(4,2)
digits.head 是 4,digits.tail 是 List(2), digits.tail.tail 是 Nil
:: 操作符从给定的头和尾创建一个新的列表:9 :: List(4,2) ,List(9,4,2)
递归遍历链表
def sum(lst: List[Int]) : Int = if( lst == Nil ) 0 else lst.head + sum(lst.tail)
模式匹配
def sum(lst: List[Int]) : Int = lst match { case Nil => 0 case h :: t => h + sum(t) // h是lst.head, t是lst.tail}
Scala类库已经有sum方法:List(9,4,2).sum
可变列表
LinkedList
// 将负值变为0var lst = scala.collection.mutable.LinkedList(1,-2,7,-9)var cur = lstwhile( cur != Nil ){ if( cur.elem < 0 ) cur.elem = 0 cur = cur.next}
// 每两个去掉一个var cur = lstwhile( curl != Nil && cur.next != Nil ){ cur.next = cur.next.next cur = cur.next}
DoubleLinkedList 多带一个prev引用
如果想把列表中的某个节点变成列表中的最后一个节点:
cur.next = LinkedList.empty
集合
集合是不重复元素的集合
Set(2,0,1) + 1 // 无效果
LinkedHashSet(链表),可以记住元素被插入的顺序
val weekdays = scala.collection.mutable.LinkedHashSet("Mo","Tu","We","Th","Fr")
SortedSet(红黑树实现)
scala.collection.immutable.SortedSet(1,2,3,4,5,6)
contains 和 subsetOf
var digits = Set(1,7,2,9)digits contains 0Set(1,2) subsetOf digits
union ( | 或 ++ ), intersect( & ), diff ( &- 或 – )
添加和移除元素的操作符
Iterator特质的重要方法
Seq特质的重要方法
将函数映射到集合
val names = List("Peter", "Paul", "Mary")names.map( _.toUpperCase ) // List("PETER","PAUL","MARY")
def ulcase(s:String) = Vector( s.toUpperCase(), s.toLowerCase() )names.map(ulcase) // List(Vector("PETER","peter"),...)names.flatMap(ulcase) // List("PETER","peter",...)
collect方法用于偏函数(并没有对所有可能的输入值进行定义的函数,它产出被定义的所有参数的函数值的集合)
"-3+4".collect { case '+' => 1; case '-' => -1 } // Vector(-1,1)
foreach
names.foreach( println )
化简、折叠和扫描
lst.reduceLeft( _ - _ )lst.reduceRight( _ - _ )lst.foldLeft(0)(_ - _) // (0 :/ lst)(_-_)lst.foldRight(0)(_ - _) // (0 :\ lst)(_-_)(1 to 10).scanLeft(0)(_+_) // 中间结果的集合(1 to 10).scanRight(0)(_+_)
拉链操作
将两个集合相互对应的元素结合在一起,长度和较短的一致
var prices = List(5.0,20.0)var quantities = List(10,2)prices zip quantities // List[(Double,Int)]( (prices zip quantities) map { p=>p._1 * p._2 } ) sum
zipAll可以指定较短集合的默认值
List(5.0,20,9.9).zipAll( List(10,2), 0.0, 1 )
zipWithIndex返回对偶的列表,每个对偶中第二个组成部分是每个元素的下标
"Scala".zipWithIndex// Vector( ('S',0), ('c',1), ... )"Scala".zipWithIndex.max._2
迭代器
可以用iterator方法从集合获得一个迭代器
while (iter.hasNext) iter.next()
for( elem <- iter ) elem
流
迭代器是一个“懒”的替代品,有需要时才去取元素,而且很脆弱,每次对next的调用都会改变迭代器的指向。
流(stream)提供的是一个不可变的替代品,流是一个尾部被懒计算的不可变列表,只有当你需要时它才会被计算。
def numsFrom( n : BigInt ): Stream[BigInt] = n #:: numsFrom( n + 1 )
#:: 操作符构建的是一个流
当调用
val tenOrMore = numsFrom(10)
得到一个被显示为
Stream(10, ?)
的流对象,尾部是未被求值的,如果调用
tenOrMore.tail.tail.tail
将会得到
Stream(13,?)
流的方法是懒执行的
val squares = numsFrom(1).map( x => x*x )
将产出
Stream(1,?)
需要squares.tail来强制对下一个元素求值
如果想得到更多,可以调用take,然后用force,强制对所有值求值
squares.take(5).force
可以从迭代器构造一个流,流将缓存访问过的行,允许重新访问它们
val words = Source.fromFile( ".." ).getLines().toStreamwords // Stream(A,?words(5) // Aachenwords // Stream( A, A's, AOL, AOL's, Aachen, ? )
懒视图
view方法产出一个其方法总是被懒执行的集合
val powers = ( 0 until 1000 ).view.map( pow(10,_) )
将产出一个为被求值的集合,当执行powers(100)时,pow(10,100)被计算。和流不同,视图并不缓存,再次调用 powers(100),将重新计算。
和流一样,force方法可以对懒视图强制求值,将得到与原集合相同类型的新集合。
懒集合对于处理需要以多种方式进行变换的大型集合有好处,避免了构建出大型中间集合的需要
(0 to 1000).map(pow(10,_)).map(1/_) // 两个操作分开执行(0 to 1000).view.map(pow(10,_)).map(1/_).force // 两个操作同时执行
与Java集合的互操作
JavaConversions对象提供了用于在Scala和Java之间来回转换的一组方法
import scala.collection.JavaConversions._var props : scala.collection.mutable.Map[String,String] = System.getProperties()props("com.horstmann.scala") = "impatient"// 将调用Properties对象的put("com.horstmann.scala", "impatient")
线程安全的集合
如果coll是个大型集合
coll.par.sum
会并发的对其求和,par方法产生当前集合的一个并行实现,该实现会尽可能地并行地执行集合方法
- 快学Scala笔记(四)
- 快学scala习题(四)
- 快学scala笔记.
- 快学Scala笔记(一)
- 快学Scala笔记(二)
- 快学Scala笔记(三)
- 快学Scala笔记(五)
- 快学scala:笔记1
- 快学scala:笔记2
- 快学scala:笔记3
- 《快学scala》笔记一
- 《快学scala》笔记及章节答案(3)
- 《快学scala》笔记及答案1
- 《快学scala》笔记及答案2
- 快学scala笔记之01-数据类型
- 快学scala笔记之02-类
- 快学scala习题(二)
- 快学scala习题(一)
- 工作笔记<序>
- java中的System的getProperty方法的取值key说明
- MySQL NULL 值处理
- POJ3186:Treats for the Cows(区间DP)
- 欢迎使用CSDN-markdown编辑器
- 快学Scala笔记(四)
- springmvc、jpa(hibernate)、mybatis组合框架搭建(一)——springmvc框架搭建
- Spring Boot (五) Repository相关
- C++ 第三章标准库类型
- MySQL 正则表达式
- JavaScript(js)处理的HTML事件、键盘事件、鼠标事件
- #HDU 1087 最大递增子序列和
- 基于Node.js搭建集成自动化测试环境的基本步骤
- 构造函数和拷贝构造的N种调⽤情况