1. Option(选项)
Scala Option(选项)类型用来表示一个值是可选的(有值或无值)。Option[T] 是一个类型为 T 的可选值的容器: 如果值存在, Option[T] 就是一个 Some[T] ,如果不存在, Option[T] 就是对象 None 。
1.1 get方法
在映射中有一个get方法,其返回值要么是None,要么是Some[T],其中T表示返回的关键字Key对应的Value值的类型。当映射关系map1中存在关键字key1时,可以调用map1.get(key1)的方式获取其返回值;如果该映射关系中不存在该关键字,则返回None。
scala> val myMap: Map[String, String] = Map("key1" -> "value")
myMap: Map[String,String] = Map(key1 -> value)
scala> val value1: Option[String] = myMap.get("key1")
value1: Option[String] = Some(value)
scala> val value2: Option[String] = myMap.get("key2")
value2: Option[String] = None
scala> val value = myMap.get("key1")
value: Option[String] = Some(value)
scala> val students = Map("zhangsan" -> 23, "lisi" -> 24, "wangwu" -> 25)
students: scala.collection.immutable.Map[String,Int] = Map(zhangsan -> 23, lisi -> 24, wangwu -> 25)
scala> students.get("zhangsan")
res0: Option[Int] = Some(23)
scala> students.get("xiaoming")
res1: Option[Int] = None
scala> val numMap = Map(1 -> 5, 2 -> 6, 3 -> 7)
numMap: scala.collection.immutable.Map[Int,Int] = Map(1 -> 5, 2 -> 6, 3 -> 7)
scala> numMap.get(1)
res2: Option[Int] = Some(5)
在上面的代码中,myMap、students 是关键字Key 类型是 String,值Value 类型是 String 的 hash map,但不一样的是它们的 get() 方法返回的分别是Option[String]和Option[Int] 的类别。由于映射myMap 里并没有 key2 这笔数据,students中也没有名字为xiaoming的Key,所以它们的get() 方法返回的都是None。
Option 有两个子类别,一个是 Some,一个是 None,当它回传 Some 的时候,代表这个函式成功地包含相应的关键字Key,而你可以透过 get() 这个函式拿到它对应的Value;如果返回的是 None,则代表该映射中没有该Key,也就不存在相应的Value值。
使用模式匹配(match)输出Key对应的Value值:
object OptionTest {
def main(args: Array[String]): Unit = {
val sites: Map[String, String] = Map("google" -> "www.google.com", "amazon" -> "www.amazon", "baidu" -> "www.baidu.com")
println( "show(sites.get('google')): " + show(sites.get("google")))
println("show(sites.get(\"taobao\"):" + show(sites.get("taobao")))
}
def show(x: Option[String]) = x match{
case Some(s: String) => s
case None => "不存在该关键字,请更换其他关键字!"
}
}
//输出结果:
//show(sites.get('google')): www.google.com
//show(sites.get("taobao"):不存在该关键字,请更换其他关键字!
上面的实例,通过模式匹配的方式处理映射的键和值,为提取映射中的值提供了另一种方式。
注意:上面两条输出语句中,第一种是使用双引号套单引号的方式,第二种使用双引号套双引号,需要使用转义字符”\”,否则会因无法解析匹配的引号而引发错误。
1.2 getOrElse方法
可以使用getOrElse方法元组中存在的元素,如果不存在该元素则可以设置返回的默认值。
有了该方法,则可以不适用上面模式匹配的方式,这样代码又精简了一点:
object OptionTest {
def main(args: Array[String]): Unit = {
val sites: Map[String, String] = Map("google" -> "www.google.com", "amazon" -> "www.amazon", "baidu" -> "www.baidu.com")
val numOption: Option[Int] = Some(6)
println(numOption.getOrElse("不存在"))
println("sites.get('baidu').getOrElse('获取关键字baidu对应的值,如果不存在该关键字,则会输出这句提示!'):" + sites.get("baidu").getOrElse("获取关键字baidu对应的值,如果不存在该关键字,则会输出这句提示!"))
}
}
//输出的结果:
//6
//sites.get('baidu').getOrElse('获取关键字baidu对应的值,如果不存在该关键字,则会输出这句提示!'):www.baidu.com
1.3 isEmpty方法
isEmpty方法可以用来检测元组中的元素是否为 None
scala> val a:Option[Int] = Some(8)
a: Option[Int] = Some(8)
scala> val b: Option[Int] = None
b: Option[Int] = None
scala> a.isEmpty
res3: Boolean = false
scala> b.isEmpty
res4: Boolean = true
1.4 iterator方法
如果选项Option包含有值,使用该方法可以迭代输出这些可选值。如果可选值为空则返回空迭代器。
下面的代码段是循环迭代输出选项Option中的各元素:
scala> val sitesOption = Option("Baidu", "Google", "Amazon", "Taobao", "Jingdong")
sitesOption: Option[(String, String, String, String, String)] = Some((Baidu,Google,Amazon,Taobao,Jingdong))
scala> val iterOption = sitesOption.iterator
iterOption: Iterator[(String, String, String, String, String)] = non-empty iterator
scala> while(iterOption.hasNext){
println(iterOption.next())
}
(Baidu,Google,Amazon,Taobao,Jingdong)
1.5 Option常用方法
下面是 Scala Option 常用的一些方法:
序号 方法及描述
1. def get: A
获取可选值
2. def isEmpty: Boolean
检测可选类型值是否为 None,是的话返回 true,否则返回 false
3. def productArity: Int
返回元素个数, A(x_1, …, x_k), 返回 k
4. def productElement(n: Int): Any
获取指定的可选项,以 0 为起始。即 A(x_1, …, x_k), 返回 x_(n+1) , 0 < n < k.
scala> val students = Map("zhangsan" -> 23, "lisi" -> 24, "wangwu" -> 25)
students: scala.collection.immutable.Map[String,Int] = Map(zhangsan -> 23, lisi -> 24, wangwu -> 25)
scala> students.get("zhangsan").productArity
res15: Int = 1
scala> students.get("zhangsan").productElement(0)
res17: Any = 23
- def exists(p: (A) => Boolean): Boolean
判断可选项中指定条件的元素是否存在,如果存在且不为 None 则返回 true,否则返回 false。 - def filter(p: (A) => Boolean): Option[A]
如果选项包含有值,而且传递给 filter 的条件函数返回 true, filter 会返回 Some 实例。 否则,返回值为 None 。 - def filterNot(p: (A) => Boolean): Option[A]
如果选项包含有值,而且传递给 filter 的条件函数返回 false, filter 会返回 Some 实例。 否则,返回值为 None 。 - def flatMap[B](f: (A) => Option[B]): Option[B]
如果选项包含有值,则传递给函数 f 处理后返回,否则返回 None - def foreach[U](f: (A) => U): Unit
如果选项包含有值,则将每个值传递给函数 f, 否则不处理。 - def getOrElse[B >: A](default: => B): B
如果选项包含有值,返回选项值,否则返回设定的默认值。 - def isDefined: Boolean
如果可选值是 Some 的实例返回 true,否则返回 false。 - def iterator: Iterator[A]
如果选项包含有值,迭代出可选值。如果可选值为空则返回空迭代器。 - def map[B](f: (A) => B): Option[B]
如果选项包含有值, 返回由函数 f 处理后的 Some,否则返回 None - def orElse[B >: A](alternative: => Option[B]): Option[B]
如果一个 Option 是 None , orElse 方法会返回传名参数的值,否则,就直接返回这个 Option。 - def orNull
如果选项包含有值返回选项值,否则返回 null。
2 Iterator(迭代器)
Scala中的Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法。
2.1 nextNext和next方法
迭代器 iterator 的两个基本操作是 next 和 hasNext。其中hasNext() 用于检测集合中是否还有元素,返回的是Boolean值,所以多放在while或if语句中,用于循环输出迭代器中的值。在判断完迭代器中还有下一个值之后,调用next()方法会返回迭代器的下一个元素,并且更新迭代器的状态。
下面是在spark-shell中,使用迭代器逐个返回Iterator的所有元素的过程:
scala> val iter = Iterator("Baidu", "Google", "Amazon", "Taobao", "Jingdong")
iter: Iterator[String] = non-empty iterator
scala> while(iter.hasNext){
println(iter.next)
}
//输出结果:
Baidu
Google
Amazon
Taobao
Jingdong
2.2 min和max方法
可以使用Iterator的 min 和 max 方法从迭代器中查找最大与最小元素。但好像同一个迭代器只能使用一次,以为Iterator的max和min方法是TraversableOnce(可遍历一次,遍历过一次之后迭代器就变为空的了)类型的,所以当第二次调用同样的方法,或第一次调用max方法第二次调用min方法时,第二次调用的方法会出现下面的错误:
scala> val iter1 = Iterator(1, 3, 2, 5, 4, 9, 6)
iter1: Iterator[Int] = non-empty iterator
scala> val iter2 = Iterator(6, 8, 5, 9, 3, 7, 2)
iter2: Iterator[Int] = non-empty iterator
scala> println("iter1 max: " + iter1.max )
iter1 max: 9
scala> println("iter1 min: " + iter1.min )
java.lang.UnsupportedOperationException: empty.min
at scala.collection.TraversableOnce$class.min(TraversableOnce.scala:222)
at scala.collection.AbstractIterator.min(Iterator.scala:1336)
... 46 elided
scala> println("iter2 min: " + iter2.min )
iter2 min: 2
scala> println("iter2 min: " + iter2.min )
java.lang.UnsupportedOperationException: empty.min
at scala.collection.TraversableOnce$class.min(TraversableOnce.scala:222)
at scala.collection.AbstractIterator.min(Iterator.scala:1336)
... 46 elided
scala> println("iter2 max: " + iter2.max )
java.lang.UnsupportedOperationException: empty.max
at scala.collection.TraversableOnce$class.max(TraversableOnce.scala:229)
at scala.collection.AbstractIterator.max(Iterator.scala:1336)
... 46 elided
//迭代器遍历过一次之后,就编程空的了
scala> iter1
res39: Iterator[Int] = empty iterator
scala> iter2
res40: Iterator[Int] = empty iterator
2.3 获取迭代器的长度
在Iterator中,可以调用size或length方法获取迭代器中的元素个数。
scala> val iter1 = Iterator(1, 3, 2, 5, 4, 9, 6)
iter1: Iterator[Int] = non-empty iterator
scala> val iter2 = Iterator(6, 8, 5, 9, 3, 7, 2, 3, 6, 8)
iter2: Iterator[Int] = non-empty iterator
scala> println("iter1.size = " + iter1.size )
iter1.size = 7
scala> println("iter2.length = " + iter2.length )
iter2.length = 10
2.4 Iterator中的常用方法
下面列出了 Scala Iterator 常用的一些方法:
1. def hasNext: Boolean
如果还有可返回的元素,返回true。
2. def next(): A
返回迭代器的下一个元素,并且更新迭代器的状态
3. def ++(that: => Iterator[A]): Iterator[A]
合并两个迭代器
4. def ++[B >: A](that :=> GenTraversableOnce[B]): Iterator[B]
合并两个迭代器
scala> val iter1 = Iterator(1, 3, 2, 5, 4, 9, 6)
iter1: Iterator[Int] = non-empty iterator
scala> val iter2 = Iterator(6, 8, 5, 9, 3, 7, 2, 3, 6, 8)
iter2: Iterator[Int] = non-empty iterator
scala> val iter = iter1 ++ iter2
iter: Iterator[Int] = non-empty iterator
scala> while(iter.hasNext){
print(iter.next + "\t")
}
1 3 2 5 4 9 6 6 8 5 9 3 7 2 3 8
5.def addString(b: StringBuilder): StringBuilder
添加一个字符串到 StringBuilder b
6. def addString(b: StringBuilder, sep: String): StringBuilder
添加一个字符串到 StringBuilder b,并指定分隔符
7. def buffered: BufferedIterator[A]
迭代器都转换成 BufferedIterator
scala> val iter1 = Iterator(1, 3, 2, 5, 4, 9, 6)
iter1: Iterator[Int] = non-empty iterator
scala> val iter2 = Iterator(6, 8, 5, 9, 3, 7, 2, 3, 6, 8)
iter2: Iterator[Int] = non-empty iterator
scala> val builder1 = new StringBuilder()
builder1: StringBuilder =
//未指定分隔符的addString方法
scala> iter1.addString(bulider1)
res42: StringBuilder = 1325496
scala> val builder2 = new StringBuilder()
builder2: StringBuilder =
//指定分隔符的addString方法
scala> iter2.addString(builder2, ",")
res45: StringBuilder = 6,8,5,9,3,7,2,3,6,8
//测试buffered方法
scala> val iter1 = Iterator(1, 3, 2, 5, 4, 9, 6)
iter1: Iterator[Int] = non-empty iterator
scala> val iter2 = Iterator(6, 8, 5, 9, 3, 7, 2, 3, 6, 8)
iter2: Iterator[Int] = non-empty iterator
scala> val buffer1 = iter1.buffered
buffer1: scala.collection.BufferedIterator[Int] = non-empty iterator
scala> while(buffer1.hasNext){
| println(buffer1.next)
| }
1
3
2
5
4
9
6
8 def contains(elem: Any): Boolean
检测迭代器中是否包含指定元素
9 def copyToArray(xs: Array[A], start: Int, len: Int): Unit
将迭代器中选定的值传给数组
10 def count(p: (A) => Boolean): Int
返回迭代器元素中满足条件p的元素总数。
//检测迭代器中是否包含指定的元素
scala> val iter1 = Iterator(1, 3, 2, 5, 4, 9, 6)
iter1: Iterator[Int] = non-empty iterator
scala> iter1.contains(6)
res50: Boolean = true
//调用过contains方法后,迭代器变为空的
scala> iter1
res51: Iterator[Int] = empty iterator
//使用copyToArray方法,将迭代器中从索引1下标开始的6个元素复制到数组arr中
scala> val iter2 = Iterator(6, 8, 5, 9, 3, 7, 2, 3, 6, 8)
iter2: Iterator[Int] = non-empty iterator
scala> val arr = new Array[Int](10)
arr: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
scala> iter2.copyToArray(arr, 1, 6)
scala> arr
res53: Array[Int] = Array(0, 6, 8, 5, 9, 3, 7, 0, 0, 0)
//使用count方法,统计迭代器iter1中大于5的元素个数
scala> val iter1 = Iterator(1, 3, 2, 5, 4, 9, 6)
iter1: Iterator[Int] = non-empty iterator
scala> iter1.count( _ > 5)
res56: Int = 2
11 def drop(n: Int): Iterator[A] //n: Int 参数变量
返回丢弃前n个元素后的新集合
12 def dropWhile(p: (A) => Boolean): Iterator[A]
从左向右丢弃元素,直到条件p不成立
13 def duplicate: (Iterator[A], Iterator[A])
生成两个能分别返回迭代器所有元素的迭代器。
14 def exists(p: (A) => Boolean): Boolean //p: (A) => Boolean 表示返回Boolean类型的函数,以函数名作为参数进行传递
返回一个布尔值,指明迭代器元素中是否存在满足p的元素。
15 def filter(p: (A) => Boolean): Iterator[A]
返回一个新迭代器 ,指向迭代器元素中所有满足条件p的元素。
scala> def doubleData(x: Int): Boolean = {
| if(x % 2 == 0) false
| else true
| }
doubleData: (x: Int)Boolean
scala> val iter2 = Iterator(6, 8, 5, 9, 3, 7, 2, 3, 6, 8)
iter2: Iterator[Int] = non-empty iterator
scala> val iter = iter2.filter(doubleData)
iter: Iterator[Int] = non-empty iterator
scala> while(iter.hasNext)
| {
| print(iter.next + ", ")
| }
5, 9, 3, 7, 3,
16 def filterNot(p: (A) => Boolean): Iterator[A]
返回一个迭代器,指向迭代器元素中不满足条件p的元素。
17 def find(p: (A) => Boolean): Option[A]
返回第一个满足p的元素或None。注意:如果找到满足条件的元素,迭代器会被置于该元素之后;如果没有找到,会被置于终点。
18 def flatMap[B](f: (A) => GenTraversableOnce[B]): Iterator[B]
针对迭代器的序列中的每个元素应用函数f,并返回指向结果序列的迭代器。
19 def forall(p: (A) => Boolean): Boolean
返回一个布尔值,指明Iterator 所指元素是否都满足p。
20 def foreach(f: (A) => Unit): Unit
在迭代器返回的每个元素上执行指定的程序 f
21 def hasDefiniteSize: Boolean
如果迭代器的元素个数有限则返回true(缺省等同于isEmpty)
22 def indexOf(elem: B): Int
返回迭代器的元素中index等于elem的第一个元素所在的索引下标。注意:使用该方法后,迭代器会越过这个元素,即在下一次迭代中将这些索引过的元素跳过,下标为跳过这些元素更新之后的下标。
scala> val iter2 = Iterator(6, 8, 5, 9, 3, 7, 2, 3, 6, 8)
iter2: Iterator[Int] = non-empty iterator
scala> iter2.indexOf(6)
res60: Int = 0
scala> iter2.indexOf(8) //由于6被索引过,下一次索引后跳过该元素
res61: Int = 0
scala> iter2.indexOf(6) //由于6和8都被索引过,所以索引下标的0号元素从5开始,6第一次出现在索引为6的位置。
res62: Int = 6
23 def indexWhere(p: (A) => Boolean): Int
返回迭代器的元素中下标满足条件p的元素。注意:迭代器会越过这个元素。
24 def isEmpty: Boolean
检查迭代器是否为空, 为空返回 true,否则返回false(与hasNext相反)。
25 def isTraversableAgain: Boolean
测试此迭代器是否可以被重复遍历。
26 def length: Int
返回迭代器中元素的数量。
27 def map[B](f: (A) => B): Iterator[B]
将迭代器中的每个元素传入函数 f 后的结果生成新的迭代器。
28 def max: A
返回迭代器迭代器元素中最大的元素。
29 def min: A
返回迭代器迭代器元素中最小的元素。
30 def mkString: String
将迭代器所有元素转换成字符串。
31 def mkString(sep: String): String
将迭代器所有元素转换成字符串,并指定分隔符。
32 def nonEmpty: Boolean
检查容器中是否包含元素(相当于 hasNext)。
33 def padTo(len: Int, elem: A): Iterator[A]
首先返回迭代器所有元素,追加拷贝 elem 直到长度达到 len。
34 def patch(from: Int, patchElems: Iterator[B], replaced: Int): Iterator[B]
返回一个新迭代器,其中自索引下标为 from 的元素开始,长为 replaced 个元素被迭代器所指元素替换。
35 def product: A
返回迭代器所指数值型元素的积。
36 def sameElements(that: Iterator[_]): Boolean
判断迭代器和指定的迭代器参数是否依次返回相同元素
37 def seq: Iterator[A]
返回集合的系列视图
38 def size: Int
返回迭代器的元素数量
39 def slice(from: Int, until: Int): Iterator[A]
返回一个自原迭代器下标from到until的元素组成的新的迭代器。
40 def sum: A
返回迭代器所指数值型元素的和
41 def take(n: Int): Iterator[A]
返回前 n 个元素的新迭代器。
42 def toArray: Array[A]
将迭代器指向的所有元素归入数组并返回。
43 def toBuffer: Buffer[B]
将迭代器指向的所有元素拷贝至缓冲区 Buffer。
44 def toIterable: Iterable[A]
返回包含该可遍历集合或迭代器的所有元素的Iterable类型的数据。对于无限的迭代器,这不会终止。
45 def toIterator: Iterator[A]
把迭代器的所有元素归入一个Iterator容器并返回。
46 def toList: List[A]
把迭代器的所有元素归入列表并返回
47 def toMap[T, U]: Map[T, U]
将迭代器的所有键值对归入一个Map并返回。
48 def toSeq: Seq[A]
将迭代器的所有元素归入一个Seq容器并返回。
49 def toString(): String
将迭代器转换为字符串
50 def zip[B](that: Iterator[B]): Iterator[(A, B)
返回一个新迭代器,指向分别由迭代器和指定的迭代器 that 元素一一对应而成的二元组序列
scala> val name = Iterator("zhangsan", "lisi", "wangwu")
name: Iterator[String] = non-empty iterator
scala> val age = Iterator(23, 24, 25)
age: Iterator[Int] = non-empty iterator
scala> val info = name.zip(age)
info: Iterator[(String, Int)] = non-empty iterator
scala> while(info.hasNext)
| {
| println(info.next)
| }
(zhangsan,23)
(lisi,24)
(wangwu,25)
想要更多的方法,请查看官方API:
Scala Standard Library 2.12.4
http://www.scala-lang.org/api/current/index.html#scala.collection.Iterator