Scala - Options
Scala 的 Option[ T ] 是给定类型零个或一个元素的容器。Option[T] 可以是 Some[T] 或 None 对象,后者表示缺失的值。例如,Scala 的 Map 的 get 方法如果找到与给定键对应的值,则返回 Some(value),否则如果 Map 中未定义该键,则返回 None。
Option 类型在 Scala 程序中经常使用,你可以将它与 Java 中表示无值的 null 值进行比较。例如,java.util.HashMap 的 get 方法返回 HashMap 中存储的值,或者如果未找到值则返回 null。
假设我们有一个根据主键从数据库中检索记录的方法。
def findPerson(key: Int): Option[Person]
如果找到记录,该方法将返回 Some[Person],否则返回 None。让我们看下面的程序。
示例
object Demo {
def main(args: Array[String]) {
val capitals = Map("France" -> "Paris", "Japan" -> "Tokyo")
println("capitals.get( \"France\" ) : " + capitals.get( "France" ))
println("capitals.get( \"India\" ) : " + capitals.get( "India" ))
}
}
将上述程序保存为 Demo.scala。使用以下命令编译和执行该程序。
命令
>scalac Demo.scala >scala Demo
输出
capitals.get( "France" ) : Some(Paris) capitals.get( "India" ) : None
处理可选值的最常见方式是通过模式匹配。例如,尝试下面的程序。
示例
object Demo {
def main(args: Array[String]) {
val capitals = Map("France" -> "Paris", "Japan" -> "Tokyo")
println("show(capitals.get( \"Japan\")) : " + show(capitals.get( "Japan")) )
println("show(capitals.get( \"India\")) : " + show(capitals.get( "India")) )
}
def show(x: Option[String]) = x match {
case Some(s) => s
case None => "?"
}
}
将上述程序保存为 Demo.scala。使用以下命令编译和执行该程序。
命令
>scalac Demo.scala >scala Demo
输出
show(capitals.get( "Japan")) : Tokyo show(capitals.get( "India")) : ?
使用 getOrElse() 方法
以下示例程序展示了如何使用 getOrElse() 方法来访问值或在无值时使用默认值。
示例
object Demo {
def main(args: Array[String]) {
val a:Option[Int] = Some(5)
val b:Option[Int] = None
println("a.getOrElse(0): " + a.getOrElse(0) )
println("b.getOrElse(10): " + b.getOrElse(10) )
}
}
将上述程序保存为 Demo.scala。使用以下命令编译和执行该程序。
命令
>scalac Demo.scala >scala Demo
输出
a.getOrElse(0): 5 b.getOrElse(10): 10
使用 isEmpty() 方法
以下示例程序展示了如何使用 isEmpty() 方法检查 option 是否为 None。
示例
object Demo {
def main(args: Array[String]) {
val a:Option[Int] = Some(5)
val b:Option[Int] = None
println("a.isEmpty: " + a.isEmpty )
println("b.isEmpty: " + b.isEmpty )
}
}
将上述程序保存为 Demo.scala。使用以下命令编译和执行该程序。
命令
>scalac Demo.scala >scala Demo
输出
a.isEmpty: false b.isEmpty: true
使用 map() 方法
map() 方法允许你通过对 Option 值应用一个 function 来转换它。如果 Option 是 Some,则对包含的值应用 function。如果 Option 是 None,则返回 None。
示例
object Demo {
def main(args: Array[String]) = {
val a: Option[Int] = Some(5)
val b: Option[Int] = None
println("a.map(_ * 2): " + a.map(_ * 2))
println("b.map(_ * 2): " + b.map(_ * 2))
}
}
将上述程序保存为 Demo.scala。使用以下命令编译并执行该程序。
命令
> scalac Demo.scala > scala Demo
输出
a.map(_ * 2): Some(10) b.map(_ * 2): None
使用 flatMap() 方法
flatMap() 方法类似于 map(),但它用于应用返回 Option 的 function。这用于链式操作返回 Option 值的情况。请尝试以下使用 flatMap() 方法的示例 -
示例
object Demo {
def main(args: Array[String]) = {
val a: Option[Int] = Some(5)
val b: Option[Int] = None
println("a.flatMap(x => Some(x * 2)): " + a.flatMap(x => Some(x * 2)))
println("b.flatMap(x => Some(x * 2)): " + b.flatMap(x => Some(x * 2)))
}
}
将上述程序保存为 Demo.scala。使用以下命令编译并执行该程序。
命令
> scalac Demo.scala > scala Demo
输出
a.flatMap(x => Some(x * 2)): Some(10) b.flatMap(x => Some(x * 2)): None
使用 filter() 方法
filter() 方法允许你使用 predicate function 过滤 Option 内部的值。如果 Option 是 Some 且 predicate 满足条件,则返回原始 Option。否则,返回 None。请尝试以下使用 filter() 方法的示例 -
示例
object Demo {
def main(args: Array[String]) = {
val a: Option[Int] = Some(5)
val b: Option[Int] = None
println("a.filter(_ > 3): " + a.filter(_ > 3))
println("a.filter(_ > 8): " + a.filter(_ > 8))
println("b.filter(_ > 3): " + b.filter(_ > 3))
}
}
将上述程序保存为 Demo.scala。使用以下命令编译并执行该程序。
命令
> scalac Demo.scala > scala Demo
输出
a.filter(_ > 3): Some(5) a.filter(_ > 8): None b.filter(_ > 3): None
使用 foreach() 方法
使用 foreach() 方法,如果你有一个 Some 的 Option,可以对其中的值应用一个 function。如果 Option 是 None,则什么也不发生。此方法用于 side effects。请尝试以下使用 foreach() 方法的示例 -
示例
object Demo {
def main(args: Array[String]) = {
val a: Option[Int] = Some(5)
val b: Option[Int] = None
a.foreach(x => println("Value of a: " + x))
b.foreach(x => println("Value of b: " + x))
}
}
将上述程序保存为 Demo.scala。使用以下命令编译并执行该程序。
命令
> scalac Demo.scala > scala Demo
输出
Value of a: 5
使用 fold() 方法
使用 fold() 方法,你可以在单个表达式中处理 Some 和 None 两种情况。它接受两个 function:一个用于处理 None 情况,一个用于处理 Some 情况。请尝试以下使用 fold() 方法的示例 -
示例
object Demo {
def main(args: Array[String]) = {
val a: Option[Int] = Some(5)
val b: Option[Int] = None
println("a.fold(0)(_ * 2): " + a.fold(0)(_ * 2))
println("b.fold(0)(_ * 2): " + b.fold(0)(_ * 2))
}
}
将上述程序保存为 Demo.scala。使用以下命令编译并执行该程序。
命令
> scalac Demo.scala > scala Demo
输出
a.fold(0)(_ * 2): 10 b.fold(0)(_ * 2): 0
Scala Option 方法
以下是在处理 Option 时可以使用的重要方法。要获取完整的可用方法列表,请查看 Scala 的官方文档。
| 序号 | 方法及描述 |
|---|---|
| 1 |
def get: A 返回 option 的值。 |
| 2 |
def isEmpty: Boolean 如果 option 是 None,则返回 true,否则返回 false。 |
| 3 |
def productArity: Int 此 product 的大小。对于 product A(x_1, ..., x_k),返回 k。 |
| 4 |
def productElement(n: Int): Any 此 product 的第 n 个元素(从 0 开始)。换句话说,对于 product A(x_1, ..., x_k),返回 x_(n+1),其中 0 < n < k。 |
| 5 |
def exists(p: (A) => Boolean): Boolean 如果此 option 非空且将谓词 p 应用于此 Option 的值时返回 true,则返回 true。否则,返回 false。 |
| 6 |
def filter(p: (A) => Boolean): Option[A] 如果此 Option 非空且将谓词 p 应用于此 Option 的值返回 true,则返回此 Option。否则,返回 None。 |
| 7 |
def filterNot(p: (A) => Boolean): Option[A] 如果此 Option 非空且将谓词 p 应用于此 Option 的值返回 false,则返回此 Option。否则,返回 None。 |
| 8 |
def flatMap[B](f: (A) => Option[B]): Option[B] 如果此 Option 非空,则返回将 f 应用于此 Option 的值的计算结果。如果此 Option 为空,则返回 None。 |
| 9 |
def foreach[U](f: (A) => U): Unit 如果 option 非空,则将给定的过程 f 应用于 option 的值。否则,不执行任何操作。 |
| 10 |
def getOrElse[B >: A](default: => B): B 如果 option 非空,则返回 option 的值,否则返回评估 default 的结果。 |
| 11 |
def isDefined: Boolean 如果 option 是 Some 的实例,则返回 true,否则返回 false。 |
| 12 |
def iterator: Iterator[A] 如果 option 非空,则返回一个单例 iterator 返回 Option 的值;如果 option 为空,则返回一个空 iterator。 |
| 13 |
def map[B](f: (A) => B): Option[B] 如果此 Option 非空,则返回一个 Some 包含将 f 应用于此 Option 的值的计算结果。否则返回 None。 |
| 14 |
def orElse[B >: A](alternative: => Option[B]): Option[B] 如果此 Option 非空,则返回此 Option,否则返回评估 alternative 的结果。 |
| 15 |
def orNull 如果 option 非空,则返回 option 的值;如果为空,则返回 null。 |