Scala中的Option
Scala中的Option避免null使用大多数语言都有一个特殊的关键字或者对象来表示一个对象引用的是“无”,在Java,它是 写Java程序的时候,经常会碰到没有有意义的东西可以返回,我们返回null。 在Java 里, 这逼迫我们去check函数的返回值,或者捕获异常。这都不是明智的选择。 同时还有一个例子 Map<String,String> map = ???
String valFor2014 = map.get(“1024”); // null
if (valFor1024 == null)
abadon();
else doSomething();
null到底代表key找不到还是说1024对应的值就是null?在有些时候,会产生具有二义性的代码。 Scala的Option类型为了让所有东西都是对象的目标更加一致,也为了遵循函数式编程的习惯,Scala鼓励你在变量和函数返回值可能不会引用任何值的时候使用Option类型。
应用例子Option类型的值通常作为Scala集合类型(List,Map等)操作的返回类型。比如Map的get方法: scala> val capitals = Map("France"->"Paris","Japan"->"Tokyo","China"->"Beijing")
capitals: scala.collection.immutable.Map[String,String] = Map(France -> Paris,Japan -> Tokyo,China -> Beijing)
scala> capitals get "France"
res0: Option[String] = Some(Paris)
scala> capitals get "North Pole"
res1: Option[String] = None
当程序回传Some的时候,代表这个函式成功地给了你一个String,而你可以透过get()函数拿到那个String,如果程序返回的是None,则代表没有字符串可以给你。 在返回None,也就是没有String给你的时候,如果你还硬要调用get()来取得 String 的话,Scala一样是会抛出一个NoSuchElementException异常给你的。 我们也可以选用另外一个方法, scala> capitals get "North Pole" get
warning: there was one feature warning; re-run with -feature for details
java.util.NoSuchElementException: None.get
at scala.None$.get(Option.scala:347)
at scala.None$.get(Option.scala:345)
... 33 elided
scala> capitals get "France" get
warning: there was one feature warning; re-run with -feature for details
res3: String = Paris
scala> (capitals get "North Pole") getOrElse "Oops"
res7: String = Oops
scala> capitals get "France" getOrElse "Oops"
res8: String = Paris
通过模式匹配分离可选值,如果匹配的值是Some的话,将Some里的值抽出赋给x变量: def showCapital(x: Option[String]) = x match {
case Some(s) => s
case None => "?"
}
配合其他容器 val a: Seq[String] =
Seq("1","2","3",null,"4")
val b: Seq[Option[String]] =
Seq(Some("1"),Some("2"),Some("3"),None,Some("4"))
a.filter(_ != null).map(_.toInt)
//res0: Seq[Int] = List(1,2,3,4)
//如果你忘了检查,编译器是看不出来的,只能在跑崩的时候抛异常
b.flatMap(_.map(_.toInt))
//res1: Seq[Int] = List(1,4)
Seq(1,2,3).headOption
//res2: Option[Int] = Some(1)
Seq(1,3).find(_ == 5)
//res3: Option[Int] = None
Seq(1,3).lastOption
//res4: Option[Int] = Some(3)
Vector(1,3).reduceLeft(_ + _)
//res5: Int = 6
Vector(1,3).reduceLeftOption(_ + _)
//res6: Option[Int] = Some(6)
//在vector为空的时候也能用
Seq("a","b","c","d").map(Option(_))
//res7: Seq[Option[String]] =
// List(Some(a),Some(b),Some(c),Some(d))
//原始数据转换成option也很方便
for循环如果我们把Option当成一般的List来用,并且用一个for循环来走访这个Option的时候,如果Option是None,那这个for循环里的程序代码自然不会执行,于是我们就达到了「不用检查Option是否为None这件事。 scala> val map1 = Map("key1" -> "value1")
map1: scala.collection.immutable.Map[String,String] = Map(key1 -> value1)
scala> val value1 = map1.get("key1")
value1: Option[String] = Some(value1)
scala> val value2 = map1.get("key2")
value2: Option[String] = None
scala> def printContentLength(x: Option[String]) {
| for (c <- x){
| println(c.length)
| }
| }
printContentLength: (x: Option[String])Unit
scala> printContentLength(value1)
6
scala> printContentLength(value2)
容器操作scala> val a: Option[String] = Some("1024")
a: Option[String] = Some(1024)
scala> val b: Option[String] = None
b: Option[String] = None
scala> a.map(_.toInt)
res0: Option[Int] = Some(1024)
scala> b.map(_.toInt)
res1: Option[Int] = None
//res1: Option[Int] = None,不会甩exception
scala> a.filter(_ == "2048")
res2: Option[String] = None
scala> b.filter(_ == "2048")
res7: Option[String] = None
scala> a.getOrElse("2048")
res8: String = 1024
scala> b.getOrElse("2048")
res9: String = 2048
scala> a.map(_.toInt).map(_ + 1).map(_ / 5).map(_ / 2 == 0)
res10: Option[Boolean] = Some(false)
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |