差异

  • Either

代表一个结果的两个可能性,一个是 Right ,一个是 Left

  • Option

代表可选择的值,一个是 Some(代表有值),一个是 None (值为空);常用于结果可能为 null 的情况;

  • Try

运算的结果有两种情况,一个是运行正常,即 Success ,一个是运行出错,抛出异常 ,即 Failure ,其中 Failure 里面包含的是异常的信息;

共同点

三者都存在两种可能性的值;都可以在结果之上进行 mapflatMap 等操作;


  • Either

RightLeft 是继承自 Either 的两个 case 类;

    //Leftfinal case class Left[+A, +B](@deprecatedName('a, "2.12.0") value: A) extends Either[A, B]//Rightfinal case class Right[+A, +B](@deprecatedName('b, "2.12.0") value: B) extends Either[A, B]

Eihter 代表一个结果的两个可能性,一个是 Right ,一个是 Left ;

    import scala.io.StdIn._val in = readLine("Type Either a string or an Int: ")val result: Either[String,Int] =try Right(in.toInt)catch {case e: NumberFormatException => Left(in)}result match {case Right(x) => s"You passed me the Int: $x, which I will increment. $x + 1 = ${x+1}"case Left(x)  => s"You passed me the String: $x"}

Either 是偏向 Right 值的,在 Either 使用 mapflatMap 等操作时,只有 Either 的结果是 Right 时,才会触发操作;习惯性地将 Left 值代表不好的结果(失败的结果),Right 代表好的结果(成功的结果);

    def doubled(i: Int) = i * 2Right(42).map(doubled) // Right(84)Left(42).map(doubled)  // Left(42)

由于 Either 定义了 flatMapmap ,所以可以对 Either 使用 for comprehensions

    val right1 = Right(1)   : Right[Double, Int] //确定right1的类型val right2 = Right(2)val right3 = Right(3)val left23 = Left(23.0) : Left[Double, Int]  //确定left23的类型val left42 = Left(42.0)for {x <- right1y <- right2z <- right3} yield x + y + z // Right(6)for {x <- right1y <- right2z <- left23} yield x + y + z // Left(23.0)for {x <- right1y <- left23z <- right2} yield x + y + z // Left(23.0)

但是不支持使用守卫表达式

    for {i <- right1if i > 0} yield i// error: value withFilter is not a member of Right[Double,Int]

同样,下面也是不支持的

    for (x: Int <- right1) yield x// error: value withFilter is not a member of Right[Double,Int]

由于 for comprehensions 使用 mapflatMap ,所以必须要推导参数的类型,并且该类型必须是 Either ;特别的地方在于,由于 Either 是偏向Right 的,所以是对于Either的值为Left 必须要指定其类型,否则,该位置的默认类型为 Nothing

    for {x <- left23y <- right1z <- left42  // type at this position: Either[Double, Nothing]} yield x + y + z//            ^// error: ambiguous reference to overloaded definition,// both method + in class Int of type (x: Char)Int// and  method + in class Int of type (x: Byte)Int// match argument types (Nothing)for (x <- right2 ; y <- left23) yield x + y  // Left(23.0)for (x <- right2 ; y <- left42) yield x + y  // errorfor {x <- right1y <- left42  // type at this position: Either[Double, Nothing]z <- left23} yield x + y + z// Left(42.0), but unexpectedly a `Either[Double,String]`
  • Option

SomeNone 是继承自 Option 的两个 case 类;

    //Somefinal case class Some[+A](@deprecatedName('x, "2.12.0") value: A) extends Option[A]//Nonecase object None extends Option[Nothing]

Option 的习惯用法是把它当作集合或者monad ,通过mapflatMapfilterforeach

    //方式一val name: Option[String] = request getParameter "name"val upper = name map { _.trim } filter { _.length != 0 } map { _.toUpperCase }println(upper getOrElse "")//方式一等价于方式二val upper = for {name <- request getParameter "name" //由于For表达式的作用,如何此处返回None,那么整个表达式将返回Nonetrimmed <- Some(name.trim)upper <- Some(trimmed.toUpperCase) if trimmed.length != 0} yield upperprintln(upper getOrElse "")

另外一个习惯用法是(不太推荐)通过模式匹配:

    val nameMaybe = request getParameter "name"nameMaybe match {case Some(name) =>println(name.trim.toUppercase)case None =>println("No name value")}
  • Try

FailureSuccess 是继承自 Try 的两个 case 类;

    //Failurefinal case class Failure[+T](exception: Throwable) extends Try[T]//Successfinal case class Success[+T](value: T) extends Try[T]

Try 常用于那些存在异常的地方,通过Try 不用确定地对可能出现的异常进行处理;

    import scala.io.StdInimport scala.util.{Try, Success, Failure}def divide: Try[Int] = {val dividend = Try(StdIn.readLine("Enter an Int that you'd like to divide:\n").toInt)val divisor = Try(StdIn.readLine("Enter an Int that you'd like to divide by:\n").toInt)val problem = dividend.flatMap(x => divisor.map(y => x/y))problem match {case Success(v) =>println("Result of " + dividend.get + "/"+ divisor.get +" is: " + v)Success(v)case Failure(e) =>println("You must've divided by zero or entered something that's not an Int. Try again!")println("Info from the exception: " + e.getMessage)divide}}

在上面的例子中,可以看出 Try 的一个重要的特性,就是Try 具有管道的功能 ,flatMapmap 将那些成功完成的操作的结果包装成Success ,将那些异常包装成 Failure ,而对于 recoverrecoverWith 则是默认对 Failure 结果进行触发;

从源码层面理解 Either、Option 和 Try相关推荐

  1. spring的事务隔离_再深一点:面试工作两不误,源码级理解Spring事务

    原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处. Spring有5种隔离级别,7种传播行为.这是面试常问的内容,也是代码中经常碰到的知识点.这些知识枯燥而且乏味,其中有些非 ...

  2. 再深一点:面试工作两不误,源码级理解Spring事务

    原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处. Spring有5种隔离级别,7种传播行为.这是面试常问的内容,也是代码中经常碰到的知识点.这些知识枯燥而且乏味,其中有些非 ...

  3. spring更新后 外层事务查不到_再深一点:面试工作两不误,源码级理解Spring事务...

    原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处. Spring有5种隔离级别,7种传播行为.这是面试常问的内容,也是代码中经常碰到的知识点.这些知识枯燥而且乏味,其中有些非 ...

  4. Spring原理学习系列之三:Spring AOP原理(从源码层面分析)-------上部

    引言 本文是Spring原理分析的第三篇博文,主要阐述Spring AOP相关概念,同时从源码层面分析AOP实现原理.对于AOP原理的理解有利于加深对Spring框架的深入理解.同时我也希望可以探究S ...

  5. android 点击事件消费,Android View事件分发和消费源码简单理解

    Android View事件分发和消费源码简单理解 前言: 开发过程中觉得View事件这块是特别烧脑的,看了好久,才自认为看明白.中间上网查了下singwhatiwanna粉丝的读书笔记,有种茅塞顿开 ...

  6. 结合源码深入理解Android Crash处理流程

    应用程序crash在开发过程中还是很常见的,本文主要是从源码的角度去跟踪下Android对于crash的处理流程.App crash的全称:Application crash.而Crash又分为:na ...

  7. Android学习之Activity源码的理解(一)

    一.Activity为Android系统中四大组件之一,是Android程序的呈现层,并通过界面与用户进行交互,因此理解Activity源码是有必要的. 二.之前我写过一篇文章:http://blog ...

  8. LruCache源码的理解

    LruCache源码的理解 使用场景 在Android手机上加载图片,一般会用到三级缓存策略 内存的缓存策略,一般会用到LruCache来解决 内存用于缓存遇到的问题 1. 手机给每个应用分配的内存空 ...

  9. PointNetPointNet++源码ModelNetDataLoader理解

    PointNet&PointNet++源码ModelNetDataLoader理解 源码:https://github.com/yanx27/Pointnet_Pointnet2_pytorc ...

  10. 从源码角度理解LinearLayout#onMeasure对child的measure调用次数

    熟悉绘制流程的都知道,ViewGroup可以决定child的绘制时机以及调用次数. 今天我们就从LinearLayout开始学起,看一下它对子View的onMeasure调用次数具体是多少. 简单起见 ...

最新文章

  1. akaze特征匹配怎么去掉不合适的点_图像匹配几种常见算法与实践
  2. iOS保存model数据(自定义Model 可以存放到本地)
  3. linux oel7没有网络,rhel7/oel7上修改默认内核启动顺序的方法
  4. 8.分布式数据库HBase第4部分
  5. Codeforces 685C Optimal Point (二分、不同类型距离的相互转换)
  6. python 自定义模块的发布和安装
  7. mysql grant教程_MySQL如何使用授权命令grant
  8. python beautifulsoup4 table tr_python BeautifulSoup解析表
  9. opencv rect画旋转矩形_在opencv c中绘制旋转的矩形
  10. deep deepfm wide 区别_个性化推荐如何满足用户口味?微信看一看的技术这样做
  11. Java常用类(三):FileUtils类
  12. 如何批量设置 Word 文档的打开密码?
  13. win10 企业版2016长期服务激活教程
  14. 移动Web第七天(响应式网页:媒体查询、BootStrap)
  15. 关于cv.waitKey
  16. 如何将多个excel表格合并成一个_如何将多个PDF文档合并为一个
  17. [算法竞赛入门经典] UVA 12174 - Shuffle
  18. 双精度移位指令SHLD,SHRD
  19. 【basler】Chapter3:basler相机出现斜黑条纹
  20. A. New Year and Hurry

热门文章

  1. 手把手教你从零开始腾讯云服务器部署
  2. 程序人生:程序员如何和老板谈升职加薪
  3. 数论学习笔记之解线性方程 a*x + b*y = gcd(a,b)
  4. sqlserver Month()函数取日期不足两位的加 0
  5. 图解数据分析(4) | 核心步骤1 - 业务认知与数据初探(数据科学家入门·完结)
  6. 在 FlashGot 中调用 Axel 下载
  7. 【考研数学】五. 二重积分
  8. 一个优秀的系统分析员应该具备的三个素质
  9. 电脑电源问题,导致攒机电脑无法开机
  10. 【NBA之路】启蒙—to—詹皇—to—保罗乔治