Scala中的Option

避免null使用

大多数语言都有一个特殊的关键字或者对象来表示一个对象引用的是“无”,在Java,它是null

写Java程序的时候,经常会碰到没有有意义的东西可以返回,我们返回null。

在Java 里,null 是一个关键字,不是一个对象,所以对它调用任何方法都是非法的。因此调用方必须检查返回值,不然会有NullPointerException的异常。

这逼迫我们去check函数的返回值,或者捕获异常。这都不是明智的选择。

同时还有一个例子

Map<String, String> map = ???
String valFor2014 = map.get(“1024”); // nullif (valFor1024 == null)abadon();
else doSomething();

null到底代表key找不到还是说1024对应的值就是null?在有些时候,会产生具有二义性的代码。

Scala的Option类型

为了让所有东西都是对象的目标更加一致,也为了遵循函数式编程的习惯,Scala鼓励你在变量和函数返回值可能不会引用任何值的时候使用Option类型。

  • Option可以看作是一个容器,容器的size是1或0;
  • size为1的时候,即有值可以引用,就是一个Some[A](x: A),如Some[String]
  • size为0的时候,即没有值的情况下就是一个None,它是Option的一个子类。None被声明为一个对象,而不是一个类,因为我们只需要它的一个实例。这样,它多少有点像null关键字,但它却是一个实实在在的,有方法的对象。

应用例子

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异常给你的。

我们也可以选用另外一个方法,getOrElse。这个方法在这个Option是Some的实例时返回对应的值,而在是None的实例时返回传入的参数。换句话说,传入getOrElse的参数实际上是默认返回值。

scala> capitals get "North Pole" get
warning: there was one feature warning; re-run with -feature for details
java.util.NoSuchElementException: None.getat scala.None$.get(Option.scala:347)at scala.None$.get(Option.scala:345)... 33 elidedscala> capitals get "France" get
warning: there was one feature warning; re-run with -feature for details
res3: String = Parisscala> (capitals get "North Pole") getOrElse "Oops"
res7: String = Oopsscala> capitals get "France" getOrElse "Oops"
res8: String = Paris

通过模式匹配分离可选值,如果匹配的值是Some的话,将Some里的值抽出赋给x变量:

def showCapital(x: Option[String]) = x match {case Some(s) => scase 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, 2, 3, 4)Seq(1,2,3).headOption
//res2: Option[Int] = Some(1)Seq(1,2,3).find(_ == 5)
//res3: Option[Int] = NoneSeq(1,2,3).lastOption
//res4: Option[Int] = Some(3)Vector(1,2,3).reduceLeft(_ + _)
//res5: Int = 6Vector(1,2,3).reduceLeftOption(_ + _)
//res6: Option[Int] = Some(6)
//在vector为空的时候也能用Seq("a", "b", "c", null, "d").map(Option(_))
//res7: Seq[Option[String]] =
// List(Some(a), Some(b), Some(c), None, Some(d))
//原始数据转换成option也很方便

实际上,多亏Scala的静态类型,你并不能错误地尝试在一个可能为null的值上调用方法。虽然在Java中这是个很容易犯的错误,它在Scala却通不过编译,这是因为Java中没有检查变量是否为null的编程作为变成Scala中的类型错误(不能将Option[String]当做String来使用)。所以,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] = Nonescala> def printContentLength(x: Option[String]) {|   for (c <- x){|     println(c.length)|   }| }
printContentLength: (x: Option[String])Unitscala> printContentLength(value1)
6scala> printContentLength(value2)

容器操作

scala> val a: Option[String] = Some("1024")
a: Option[String] = Some(1024)scala> val b: Option[String] = None
b: Option[String] = Nonescala> a.map(_.toInt)
res0: Option[Int] = Some(1024)scala> b.map(_.toInt)
res1: Option[Int] = None
//res1: Option[Int] = None,不会甩exceptionscala> a.filter(_ == "2048")
res2: Option[String] = Nonescala> b.filter(_ == "2048")
res7: Option[String] = Nonescala> a.getOrElse("2048")
res8: String = 1024scala> b.getOrElse("2048")
res9: String = 2048scala> a.map(_.toInt).map(_ + 1).map(_ / 5).map(_ / 2 == 0)
res10: Option[Boolean] = Some(false)

Scala中的Option相关推荐

  1. scala中使用Option、Some、None,避免使用null

    避免null使用 大多数语言都有一个特殊的关键字或者对象来表示一个对象引用的是"无",在Java,它是null.在Java 里,null 是一个关键字,不是一个对象,所以对它调用任 ...

  2. Scala系列-4、scala中特质、柯里化、闭包等

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 传送门:大数据系列文章目录 目录 scala中特质 特质作为接口使用 特质中放置非抽象的成员 ...

  3. scala中何时使用下划线_在Scala中使用下划线

    scala中何时使用下划线 Underscore (_) character is reserved in Scala and has multiple usages in the programmi ...

  4. Scala中的None,Nothing,Null,Nil

    在scala中这四个类型名称很类似,作用确实完全不同的. None是一个object,是Option的子类型,定义如下 case object None extends Option[Nothing] ...

  5. Scala学习之Option类

    今天特意学习一下Option类型 一般来说,对于每种语言都会有一个关键字来表示一个对象引用的"无".比如在Java中使用的是null. 在Scala中是融合了函数式编程的风格,当预 ...

  6. Scala中如何优雅的处理Null

    前言 如果在scala代码还在使用id! = null,可能会被有的人嘲笑,都什么年代了,竟然还有这样的写法,NullPointerException见少了吧? 不过,据统计: Spark 源代码使用 ...

  7. 【Scala】Scala中的模式匹配、类型参数与隐式转换

    1.模式匹配 (1)概述 模式匹配是Scala中非常有特色,非常强大的一种功能.模式匹配,其实类似于Java中的swich case语法,即对一个值进行条件判断,然后针对不同的条件,进行不同的处理.但 ...

  8. scala中的match详解

    Scala中提供了比java,c更加强大的switch语句--match,而且不用担心因为忘记写break语句而发生case穿透 1.更好的switch 与if,类似match也是表达式,如下一个用于 ...

  9. scala中apply和unapply方法

    apply方法 apply方法被称作注入方法,在类的伴生对象中做一个初始化操作 apply方法的参数列表不需要跟构造器的参数列表统一 apply方法是定义在伴生对象中的 当scala中类或者对象有一个 ...

  10. Scala中解析json工具对比

    写再前面的总结: 1, 做少量文件解析,优先用json4s,因为json4s时基于Scala开发的,对scala使用场景支持更好 2. 做大量数据的解析,追求序列化.反序列化速度时,考虑用fastjs ...

最新文章

  1. 获取weblogic上指定文件的路径 java_项目部署到WebLogic文件路径访问不正确
  2. 蓝鸥Unity开发基础——Switch语句学习笔记
  3. 拦截QT关闭窗口的CloseEvent
  4. 0基础能学mysql数据库吗_mysql学习入门:零基础如何使用mysql创建数据库表?
  5. Java LineNumberInputStream available()方法与示例
  6. linux mmap系统调用
  7. MacOSX系统下HomeBrew安装指定版本的软件 IntelliJ IDEA 设置多个Go语言版本开发
  8. syntaxnet python调用
  9. [导入]设置wap服务器
  10. Win32环境下的Tomcat5.5.17与apache2.2的集群
  11. Itext学习(一)----官方网站学习
  12. 集成底座POC方案说明
  13. Win10操作系统下,如何确定电脑位数(图文教程)
  14. Notion、印象笔记、Roam research…不知道笔记系统构建方式!怎么能选到对的笔记应用?
  15. 形容人的内核是什么意思_【得到】人人都需要的精准表达术-老光
  16. 为什么软件开发周期总是预估的2~3倍?
  17. html天气预报静态页面,天气预报_HTML静态页面_带读秒时钟
  18. qt5.9开发指南 例子
  19. 【统计】假设检验方法
  20. 关于windows清理C盘问题

热门文章

  1. STM32驱动步进电机
  2. 战争机器5加速器信息:开发工作已经完成 更多内容将在科隆展上披露
  3. 各行业程序员年薪分析
  4. leetcode59 spiral matrix2
  5. 微信小程序获取openId,传参问题导致参数无效(errcode: 40013、errcode:40125、errcode“:40029)
  6. 2016 上海 Qcon 值得关注的技术
  7. 【文化课每周学习记录】2019.4.14——2019.4.20
  8. ubuntu22.04设置静态ip地址
  9. php楼梯有n级台阶,楼梯问题的一些解决方法
  10. 计算机如何将两个磁盘合在一起,win10怎么把电脑自带的两个磁盘合并到一起