理解 Scala 中的选项
在本文中,我们将学习如何在 Scala 中使用可选数据元素。Scala 中的 Options
帮助我们编写健壮的代码。
Scala 中的 Option
类型
Scala 中的 Option[T]
是一个容器
,用于存储零个或一个给定类型的值。使用 Scala 的 Option
管理可选值,我们可以确保两件事:
- 类型安全:我们可以参数化可选值。
- 功能意识:
option
类型提供了许多功能性能力,以确保在程序中产生更少的错误。
在 Scala 中,Option[T]
由 Some[T]
或 None[T]
对象表示。这里的 scala.Option
是抽象和扩展的基类,使得 Scala 中的 Option
表现得像一个容器。
请记住,Option
类及其子类需要具体类型。它们可以是显式的,也可以像下面的语法那样推断出来。
例子:
val obj1: Option[Int] = None
val obj2 = Some(100)
这里 obj1
和 obj2
是 Option[Int]
的对象。一个常见的问题是如何检查我们的 Option
是 Some
还是 None
?
为了解决这个问题,我们有以下功能。
isEmpty
:如果对象为None
,此方法返回true
。nonEmpty
:如果对象是Some
,此方法返回true
。isDefined
:如果对象是Some
,此方法返回true
。
在 Scala 中检索 Option
的值
我们可以使用 get
方法来检索 Options
值。如果在 None
的对象上调用 get
方法,则抛出 NoSuchElementException
,也称为 成功偏差
。
示例代码:
val obj1: Option[Int]= ...
val v1 = if (obj1.isDefined)
{
obj1.get
}
else
{
0
}
上面的代码也可以使用模式匹配来编写。
示例代码:
val obj1: Option[Int]= ...
val v1 = obj1 match {
case Some(temp) =>
temp
case None =>
0
}
我们还有其他方法,例如 getOrElse
和 orElse
来检索值。
getOrElse
:如果对象是Some
,此方法检索值;否则,它返回一个默认值。orElse
:如果对象是Some
,此方法检索值;否则返回一个alternate
选项。
当未设置可选值时,getOrElse
方法非常有用,因为我们可以返回默认值。
语法:
val v1 = obj1.getOrElse(0)
Option
作为 Scala 中的容器
正如我们已经看到的那样,Option
是 Scala 中另一个值的容器,就像我们遍历 List
类似,我们可以遍历 Option
。
让我们看看这个容器的一些方法。Scala 中 Option.map
方法的语法:
final def map[Y](f: (X) => Y): Option[Y]
示例代码:
val obj1: Option[Int] = Some(100)
assert(obj1.map(_.toString).contains("100"))
assert(obj1.map(_ * 2.0).contains(200))
val obj2: Option[Int] = None
assert(obj2.map(_.toString).isEmpty)
在上面的示例中,我们使用 Option.map
方法将包含的值转换为另一种类型。Option.map
方法也可用于影响程序的流控制
。
示例代码:
val obj1: Option[Int] = Some(10)
val obj2: Option[Int] = None
def mul(n: Int): Int = n * 2
assert(obj1.map(mul).contains(20))
assert(obj2.map(mul).isEmpty)
这里我们创建了两个 Option[Int]
对象,第一个对象的值为 10
,第二个对象为空。然后我们定义了一个方法 mul
将输入乘以 2
。
最后,我们使用 mul
方法映射 obj1
和 obj2
。映射 obj1 给我们 Some(20)
,映射 obj2 给我们 None
。
这里要注意的一件事是,在第二次调用 obj2.map(mul)
中,根本没有调用 mul
方法。我们也可以通过过滤进行流量控制。
我们有很多方法可以做到这一点:
filter
:如果Options
值为Some
并且提供的函数返回true
,则此方法返回Option
。exists
:如果设置了Option
并且提供的函数返回true
,则此方法返回true
。forall
:行为与exists
方法相同。
使用这些函数,我们可以非常简洁地编写代码。
让我们举一个例子,我们找到得分最高的球队。
示例代码:
def highScoringTeam(playerA: Player, playerB: Player, tournament: Tournament): Option[(Player, Int)] =
{ getTopScore(playerA, tournament).foldRight(getTopScore(playerB, tournament)) {
case (playerAInfo, playerBInfo) => playerBInfo.filter {
case (_, scoreB) => scoreB > playerAInfo._2
}.orElse(Some(playerAInfo))
}
}
在上面的代码中,我们利用了 Options
可以用作集合。唯一的区别是 Option 最多可以有一个值。