Scala学习之——Option、Iterator

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
  1. def exists(p: (A) => Boolean): Boolean
    判断可选项中指定条件的元素是否存在,如果存在且不为 None 则返回 true,否则返回 false。
  2. def filter(p: (A) => Boolean): Option[A]
    如果选项包含有值,而且传递给 filter 的条件函数返回 true, filter 会返回 Some 实例。 否则,返回值为 None 。
  3. def filterNot(p: (A) => Boolean): Option[A]
    如果选项包含有值,而且传递给 filter 的条件函数返回 false, filter 会返回 Some 实例。 否则,返回值为 None 。
  4. def flatMap[B](f: (A) => Option[B]): Option[B]
    如果选项包含有值,则传递给函数 f 处理后返回,否则返回 None
  5. def foreach[U](f: (A) => U): Unit
    如果选项包含有值,则将每个值传递给函数 f, 否则不处理。
  6. def getOrElse[B >: A](default: => B): B
    如果选项包含有值,返回选项值,否则返回设定的默认值。
  7. def isDefined: Boolean
    如果可选值是 Some 的实例返回 true,否则返回 false。
  8. def iterator: Iterator[A]
    如果选项包含有值,迭代出可选值。如果可选值为空则返回空迭代器。
  9. def map[B](f: (A) => B): Option[B]
    如果选项包含有值, 返回由函数 f 处理后的 Some,否则返回 None
  10. def orElse[B >: A](alternative: => Option[B]): Option[B]
    如果一个 Option 是 None , orElse 方法会返回传名参数的值,否则,就直接返回这个 Option。
  11. 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)         //由于68都被索引过,所以索引下标的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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

love666666shen

谢谢您的鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值