Spark(八) scala中的Option、Some、None

一、避免null的使用

大多數(shù)語(yǔ)言都有一個(gè)特殊的關(guān)鍵字或者對(duì)象來(lái)表示一個(gè)對(duì)象引用的是“無(wú)”,在Java,它是null。在Java 里,null 是一個(gè)關(guān)鍵字,不是一個(gè)對(duì)象,所以對(duì)它調(diào)用任何方法都是非法的。但是這對(duì)語(yǔ)言設(shè)計(jì)者來(lái)說(shuō)是一件令人疑惑的選擇。為什么要在程序員希望返回一個(gè)對(duì)象的時(shí)候返回一個(gè)關(guān)鍵字呢?

二、Scala的Option的類型

Option是針對(duì)Map等集合操作的
為了讓所有東西都是對(duì)象的目標(biāo)更加一致,也為了遵循函數(shù)式編程的習(xí)慣,Scala鼓勵(lì)你在變量和函數(shù)返回值可能不會(huì)引用任何值的時(shí)候使用Option類型。在沒(méi)有值的時(shí)候,使用None,這是Option的一個(gè)子類。如果有值可以引用,就使用Some來(lái)包含這個(gè)值。Some也是Option的子類。
None被聲明為一個(gè)對(duì)象,而不是一個(gè)類,因?yàn)槲覀冎恍枰囊粋€(gè)實(shí)例。這樣,它多少有點(diǎn)像null關(guān)鍵字,但它卻是一個(gè)實(shí)實(shí)在在的,有方法的對(duì)象。

  • 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

Option有兩個(gè)子類別,Some和None。當(dāng)程序回傳Some的時(shí)候,代表這個(gè)函式成功地給了你一個(gè)String,而你可以透過(guò)get()函數(shù)拿到那個(gè)String,如果程序返回的是None,則代表沒(méi)有字符串可以給你

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

通過(guò)模式匹配可分離可選值,如果匹配的值是Some的話,將Some里的值抽出賦給X變量

def showCapital(x: Option[String]) = x match {
    case Some(s) => s
    case None => "?"
}

三、詳解Option[T]

在Scala里Option[T]實(shí)際上是一個(gè)容器,就像數(shù)組或是List一樣,你可以把他看成是一個(gè)可能有零到一個(gè)元素的List。
當(dāng)你的Option里面有東西的時(shí)候,這個(gè)List的長(zhǎng)度是1(也就是 Some),而當(dāng)你的Option里沒(méi)有東西的時(shí)候,它的長(zhǎng)度是0(也就是 None)

四、for循環(huán)

如果我們把Option當(dāng)成一般的List來(lái)用,并且用一個(gè)for循環(huán)來(lái)走訪這個(gè)Option的時(shí)候,如果Option是None,那這個(gè)for循環(huán)里的程序代碼自然不會(huì)執(zhí)行,于是我們就達(dá)到了「不用檢查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)

五、map操作

在函數(shù)式編程中有一個(gè)核心的概念之一是轉(zhuǎn)換,所以大部份支持函數(shù)式編程語(yǔ)言,都支持一種叫map()的動(dòng)作,這個(gè)動(dòng)作是可以幫你把某個(gè)容器的內(nèi)容,套上一些動(dòng)作之后,變成另一個(gè)新的容器。
現(xiàn)在我們考慮如何用Option的map方法實(shí)現(xiàn)length: xxx的輸出形式:

先算出 Option 容器內(nèi)字符串的長(zhǎng)度
然后在長(zhǎng)度前面加上 "length: " 字樣
最后把容器走訪一次,印出容器內(nèi)的東西

scala> value1.map(_.length).map("length: " + _).foreach(println)
length: 6
 
scala> value1.map("length: " + _.length).foreach(println)
length: 6
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容