Scala的Option/Some/None操作:

一、环境:Idea 16+Jdk-1.7+Scala-2.10.4

二、测试代码:

import scala.io.Source
import scala.util.{Try,Success,Failure}/*** Document:本类作用---->测试Options、Some、None* User: yangjf* Date: 2016/9/25  12:48*/
object Options {def main(args: Array[String]) {//1、获取操作后的返回值println(toInt("23"))println(toInt("23").get)println(toInt("abc"))
//    println(toInt("abc").get)  ---->报错误,因为没有返回值val xx = if (toInt("foo").isDefined) toInt("foo") else 0println("处理结果:"+xx)//2、Use  getOrElse--->如果方法执行成功,则返回实际值,否则返回失败println(toInt("1").getOrElse(2))   //返回1println(toInt("as").getOrElse(2))  //执行失败,返回2// 3、Use  foreach//有返回值toInt("1").foreach{ i =>println(s"Got an int: $i")}//没有返回值toInt("abc").foreach{ i =>println(s"Got an int: $i")}//4、Use a match expressiontoInt("1") match {case Some(i) => println(i)case None => println("That didn't work.")}//5、测试过滤不需要的值,返回Listmy_test//6、一行一行地读取文件println("文件读取:"+readTextFile("E:/idea16/my-hbase-test/txt/test.txt"))println("文件读取2:"+readTextFile2("E:/idea16/my-hbase-test/txt/test.txt"))//7、除法计算产生异常println("除法产生异常:"+divideXByY(1,3))println("除法产生异常:"+divideXByY(3,1))println("除法产生异常:"+divideXByY(3,0))println("除法产生异常:"+divideXByY(0,3))val x = divideXByY(1, 1).getOrElse(0)val y = divideXByY(1, 0).getOrElse(0)println("x---->"+x)println("y---->"+y)divideXByY(1, 1).foreach(println)divideXByY(1, 0).foreach(println)divideXByY(1, 1) match {case Success(i) => println(s"Success, value is: $i")case Failure(s) => println(s"Failed, message is: $s")}//yield操作val z = for {a <- Try(x.toInt)b <- try="" y="" toint="" yield="" a="" b="" val="" answer="z.getOrElse(0)" 2="" println="" answer="" is="" answer="" 8="" println="" dividexbyy2="" 1="" 0="" println="" 2="" dividexbyy2="" 6="" 2="" val="" m="divideXByY2(1," 1="" right="" getorelse="" 0="" returns="" 1="" val="" n="divideXByY2(1," 0="" right="" getorelse="" 0="" returns="" 0="" println="" m="" m="" println="" n="" n="" prints="" answer:="" dude="" can="" t="" divide="" by="" 0="" dividexbyy2="" 1="" 0="" match="" case="" left="" s=""> println("Answer: " + s)case Right(i) => println("Answer: " + i)}}//Using Option with Scala collectionsdef my_test()={//options非常好的特性val bag = List("1", "2", "foo", "3", "bar")val res: List[Option[Int]] =bag.map(toInt) //返回处理后的值println("res list: "+res)//可以添加其中的int为map,使用flatten方法/***   *    val xs = List(*               Set(1, 2, 3),*               Set(1, 2, 3)*             ).flatten*    // xs == List(1, 2, 3, 1, 2, 3)*    val ys = Set(*               List(1, 2, 3),*               List(3, 2, 1)*             ).flatten*    // ys == Set(1, 2, 3)*/val ends: List[Int] =res.flattenprintln("flatten转换后的结果:"+ends)val ends2=bag.flatMap(toInt)println("flatMap转换后的结果2:"+ends2)//collect方法同样可以实现以上效果val ends3: List[Int] =bag.map(toInt).collect{case Some(i) => i} //匿名函数忽略了没有的值println("collect实现的效果:"+ends3)}//Returning an Option from a method//Getting the value from an Optiondef toInt(s: String): Option[Int] = {try {Some(Integer.parseInt(s.trim))} catch {case e: Exception => None}}//Using Option with other frameworks
//  def getAll() : List[Stock] = {
//    DB.withConnection { implicit connection =>
//      sqlQuery().collect {
//        // the 'company' field has a value
//        case Row(id: Int, symbol: String, Some(company: String)) =>
//          Stock(id, symbol, Some(company))
//        // the 'company' field does not have a value
//        case Row(id: Int, symbol: String, None) =>
//          Stock(id, symbol, None)
//      }.toList
//    }
//  }
//  verifying("If age is given, it must be greater than zero",
//    model =>
//      model.age match {
//        case Some(age) => age < 0
//        case None => true
//      }
//  )import scala.util.control.Exception._//文件读取def readTextFile(f: String): Option[List[String]] =allCatch.opt(Source.fromFile(f).getLines.toList) //直接就获取所有异常信息def readTextFile2(filename: String): Try[List[String]] = {Try(Source.fromFile(filename).getLines.toList)}//Using Try, Success, and Failureimport scala.util.{Try,Success,Failure}def divideXByY(x: Int, y: Int): Try[Int] = {Try(x / y)}//Using Either, Left, and Rightdef divideXByY2(x: Int, y: Int): Either[String, Int] = {if (y == 0) Left("Dude, can't divide by 0")else Right(x / y)}
}

三、打印结果:

Some(23)
23
None
处理结果:0
1
2
Got an int: 1
1
res list: List(Some(1), Some(2), None, Some(3), None)
flatten转换后的结果:List(1, 2, 3)
flatMap转换后的结果2:List(1, 2, 3)
collect实现的效果:List(1, 2, 3)
文件读取:Some(List(12, 23, 23, 45, 34, 56))
文件读取2:Success(List(12, 23, 23, 45, 34, 56))
除法产生异常:Success(0)
除法产生异常:Success(3)
除法产生异常:Failure(java.lang.ArithmeticException: / by zero)
除法产生异常:Success(0)
x---->1
y---->0
1
Success, value is: 1
answer is 0
匹配结果:Left(Dude, can't divide by 0)
匹配结果2:Right(3)
m  1
n  0
Answer: Dude, can't divide by 0

四、对应的英文原文如下:

20.6. Using the Option/Some/None Pattern
Problem
For a variety of reasons, including removing  null values from your code, you want to
use what I call the  Option / Some / None pattern. Or, if you’re interested in a problem (ex‐
ception) that occurred while processing code, you may want to return  Try / Success /
Failure from a method instead of  Option / Some / None .Solution
There is some overlap between this recipe and the previous recipe, “Eliminate null Val‐
ues from Your Code”. That recipe shows how to use  Option instead of  null in the
following situations:
• Using  Option in method and constructor parameters
• Using  Option to initialize class fields (instead of using  null )
• Converting  null results from other code (such as Java code) into an  Option
See that recipe for examples of how to use an  Option in those situations.This recipe adds these additional solutions:
• Returning an  Option from a method
• Getting the value from an  Option
• Using  Option with collections
• Using  Option with frameworks
• Using  Try / Success / Failure when you need the error message (Scala 2.10 and
newer)
• Using  Either / Left / Right when you need the error message (pre-Scala 2.10)
Returning an Option from a method
The  toInt method used in this book shows how to return an  Option from a method. It
takes a  String as input and returns a  Some[Int] if the  String is successfully converted
to an  Int , otherwise it returns a  None :def toInt(s: String): Option[Int] = {
try {
Some(Integer.parseInt(s.trim))
} catch {
case e: Exception => None
}
}Although this is a simple method, it shows the common pattern, as well as the syntax.
For a more complicated example, see the  readTextFile example in Recipe 20.5.
This is what  toInt looks like in the REPL when it succeeds and returns a  Some :scala> val x = toInt("1")
x: Option[Int] = Some(1)
This is what it looks like when it fails and returns a  None :
scala> val x = toInt("foo")
x: Option[Int] = NoneGetting the value from an Option
The  toInt example shows how to declare a method that returns an  Option . As a con‐
sumer of a method that returns an  Option , there are several good ways to call it and
access its result:
• Use  getOrElse
• Use  foreach
• Use a match expression20.6. Using the Option/Some/None Pattern To get the actual value if the method succeeds, or use a default value if the method fails,
use  getOrElse :scala> val x = toInt("1").getOrElse(0)
x: Int = 1
Because an  Option is a collection with zero or one elements, the  foreach method can
be used in many situations:toInt("1").foreach{ i =>
println(s"Got an int: $i")
}That example prints the value if  toInt returns a  Some , but bypasses the  println state‐
ment if  toInt returns a  None .
Another good way to access the  toInt result is with a match expression:toInt("1") match {
case Some(i) => println(i)
case None => println("That didn't work.")
}Using Option with Scala collections
Another great feature of  Option is that it plays well with Scala collections. For instance,
starting with a list of strings like this:val bag = List("1", "2", "foo", "3", "bar")
imagine you want a list of all the integers that can be converted from that list of strings.
By passing the  toInt method into the  map method, you can convert every element in
the collection into a  Some or  None value:scala> bag.map(toInt)
res0: List[Option[Int]] = List(Some(1), Some(2), None, Some(3), None)This is a good start. Because an  Option is a collection of zero or one elements, you can
convert this list of  Int values by adding  flatten to  map :scala> bag.map(toInt).flatten
res1: List[Int] = List(1, 2, 3)
As shown in Recipe 10.16, “Combining map and flatten with flatMap”, this is the same
as calling  flatMap :scala> bag.flatMap(toInt)
res2: List[Int] = List(1, 2, 3)The  collect method provides another way to achieve the same result:
scala> bag.map(toInt).collect{case Some(i) => i}
res3: List[Int] = List(1, 2, 3)
That example works because the  collect method takes a partial function, and the
anonymous function that’s passed in is only defined for  Some values; it ignores the  None
values.These examples work for several reasons:
• toInt is defined to return  Option[Int] .
• Methods like  flatten ,  flatMap , and others are built to work well with  Option
values.
• You can pass anonymous functions into the collection methods.
Using Option with other frameworks
Once you begin working with third-party Scala libraries, you’ll see that  Option is used
to handle situations where a variable may not have a value. For instance, they’re baked
into the Play Framework’s Anorm database library, where you use  Option / Some / None
for database table fields that can be  null . In the following example, the third field may
be  null in the database, so it’s handled using  Some and  None , as shown:def getAll() : List[Stock] = {
DB.withConnection { implicit connection =>
sqlQuery().collect {
// the 'company' field has a value
case Row(id: Int, symbol: String, Some(company: String)) =>
Stock(id, symbol, Some(company))
// the 'company' field does not have a value
case Row(id: Int, symbol: String, None) =>
Stock(id, symbol, None)
}.toList
}
}The  Option approach is also used extensively in Play validation methods:
verifying("If age is given, it must be greater than zero",
model =>
model.age match {
case Some(age) => age < 0
case None => true
}
)The  scala.util.control.Exception object gives you another way to
use an  Option , depending on your preferences and needs. For in‐
stance, the  try / catch block was removed from the following method
and replaced with an  allCatch method:import scala.util.control.Exception._
def readTextFile(f: String): Option[List[String]] =
allCatch.opt(Source.fromFile(f).getLines.toList)allCatch is described as a  Catch object “that catches everything.” The
opt method returns  None if an exception is caught (such as a
FileNotFoundException ), and a  Some if the block of code succeeds.
Other  allCatch methods support the  Try and  Either approaches. See
the Exception object Scaladoc for more information.
If you like the  Option / Some / None approach, but want to write a method that returns
error information in the failure case (instead of  None , which doesn’t return any error
information), there are two similar approaches:• Try ,  Success , and  Failure (introduced in Scala 2.10)
• Either ,  Left , and  Right
I prefer the new  Try / Success / Failure approach, so let’s look at it next.
Using Try, Success, and Failure
Scala 2.10 introduced  scala.util.Try as an approach that’s similar to  Option , but re‐
turns failure information rather than a  None .
The result of a computation wrapped in a  Try will be one of its subclasses:  Success or
Failure . If the computation succeeds, a  Success instance is returned; if an exception
was thrown, a  Failure will be returned, and the  Failure will hold information about
what failed.To demonstrate this, first import the new classes:
import scala.util.{Try,Success,Failure}
Then create a simple method:
def divideXByY(x: Int, y: Int): Try[Int] = {
Try(x / y)
}This method returns a successful result as long as  y is not zero. When  y is zero, an
ArithmeticException happens. However, the exception isn’t thrown out of the method;
it’s caught by the  Try , and a  Failure object is returned from the method.
The method looks like this in the REPL:scala> divideXByY(1,1)
res0: scala.util.Try[Int] = Success(1)
scala> divideXByY(1,0)
res1: scala.util.Try[Int] = Failure(java.lang.ArithmeticException: / by zero)As with an  Option , you can access the  Try result using  getOrElse , a  foreach method,
or a match expression. If you don’t care about the error message and just want a result,use  getOrElse :
// Success
scala> val x = divideXByY(1, 1).getOrElse(0)
x: Int = 1
// Failure
scala> val y = divideXByY(1, 0).getOrElse(0)
y: Int = 0Using a  foreach method also works well in many situations:scala> divideXByY(1, 1).foreach(println)
1
scala> divideXByY(1, 0).foreach(println)
(no output printed)
If you’re interested in the  Failure message, one way to get it is with a match expression:
divideXByY(1, 1) match {
case Success(i) => println(s"Success, value is: $i")
case Failure(s) => println(s"Failed, message is: $s")
}Another approach is to see if a  Failure was returned, and then call its  toString method
(although this doesn’t really follow the “Scala way”):scala> if (x.isFailure) x.toString
res0: Any = Failure(java.lang.ArithmeticException: / by zero)
The  Try class has the added benefit that you can chain operations together, catching
exceptions as you go. For example, the following code won’t throw an exception, re‐
gardless of what the values of  x and  y are:val z = for {
a <- Try(x.toInt)
b <- try="" y="" toint="" yield="" a="" b="" val="" answer="z.getOrElse(0)" 2="" if="" x="" and="" y="" are="" string="" values="" like="" 1="" and="" 2="" this="" code="" works="" as="" expected="" with="" answer="" resulting="" in="" an="" int="" value="" if="" x="" or="" y="" is="" a="" string="" that="" can="" t="" be="" converted="" to="" an="" int="" z="" will="" have="" this="" value:="" z:="" scala="" util="" try="" int="" failure="" java="" lang="" numberformatexception:="" for="" input="" string:="" one="" if="" x="" or="" y="" is="" null="" z="" will="" have="" this="" value:="" z:="" scala="" util="" try="" int="" failure="" java="" lang="" numberformatexception:="" null="" in="" either="" failure="" case="" the="" getorelse="" method="" protects="" us="" returning="" the="" default="" value="" of="" 0="" the="" readtextfile="" method="" in="" recipe="" 20="" 5="" shows="" another="" try="" example="" the="" method="" from="" that="" example="" is="" repeated="" here:="" def="" readtextfile="" filename:="" string="" :="" try="" list="" string="" try="" source="" fromfile="" filename="" getlines="" tolist="" if="" the="" readtextfile="" method="" runs="" successfully="" the="" lines="" from="" the="" etc="" passwd="" file="" are="" printed="" but="" if="" an="" exception="" happens="" while="" trying="" to="" open="" and="" read="" the="" file="" the="" failure="" line="" in="" the="" match="" expression="" prints="" the="" error="" like="" this:="" java="" io="" filenotfoundexception:="" foo="" bar="" no="" such="" file="" or="" directory="" the="" try="" class="" includes="" a="" nice="" collection="" of="" methods="" that="" let="" you="" handle="" situations="" in="" many="" ways="" including:="" collection-like="" implementations="" of="" filter="" flatmap="" flatten="" foreach="" and="" map="" get="" getorelse="" and="" orelse="" tooption="" which="" lets="" you="" treat="" the="" result="" as="" an="" option="" recover="" recoverwith="" and="" transform="" which="" let="" you="" gracefully="" handle="" success="" and="" failure="" results="" as="" you="" can="" see="" try="" is="" a="" powerful="" alternative="" to="" using="" option="" some="" none="" using="" either="" left="" and="" right="" prior="" to="" scala="" 2="" 10="" an="" approach="" similar="" to="" try="" was="" available="" with="" the="" either="" left="" and="" right="" classes="" with="" these="" classes="" either="" is="" analogous="" to="" try="" right="" is="" similar="" to="" success="" and="" left="" is="" similar="" to="" failure="" the="" following="" method="" demonstrates="" how="" to="" implement="" the="" either="" approach:="" def="" dividexbyy="" x:="" int="" y:="" int="" :="" either="" string="" int="" if="" y="=" 0="" left="" dude="" can="" t="" divide="" by="" 0="" else="" right="" x="" y="" as="" shown="" your="" method="" should="" be="" declared="" to="" return="" an="" either="" and="" the="" method="" body="" should="" return="" a="" right="" on="" success="" and="" a="" left="" on="" failure="" the="" right="" type="" is="" the="" type="" your="" method="" returns="" when="" it="" runs="" successfully="" an="" int="" in="" this="" case="" and="" the="" left="" type="" is="" typically="" a="" string="" because="" that="" s="" how="" the="" error="" message="" is="" returned="" as="" with="" option="" and="" try="" a="" method="" returning="" an="" either="" can="" be="" called="" in="" a="" variety="" of="" ways="" including="" getorelse="" or="" a="" match="" expression:="" val="" x="divideXByY(1," 1="" right="" getorelse="" 0="" returns="" 1="" val="" x="divideXByY(1," 0="" right="" getorelse="" 0="" returns="" 0="" prints="" answer:="" dude="" can="" t="" divide="" by="" 0="" dividexbyy="" 1="" 0="" match="" case="" left="" s=""> println("Answer: " + s)
case Right(i) => println("Answer: " + i)
}You can also access the error message by testing the result with  isLeft , and then ac‐
cessing the  left value, but this isn’t really the Scala way:
scala> val x = divideXByY(1, 0)
x: Either[String,Int] = Left(Dude, can't divide by 0)
scala> x.isLeft
res0: Boolean = true
scala> x.left
res1: scala.util.Either.LeftProjection[String,Int] =
LeftProjection(Left(Dude, can't divide by 0))
Although the  Either classes offered a potential solution prior to Scala 2.10, I now use
the  Try classes in all of my code instead of  Either .
Discussion
As shown in the Solution, if there’s a weakness of using  Option , it’s that it doesn’t tell
you why something failed; you just get a  None instead of a  Some . If you need to know
why something failed, use  Try instead of  Option .
Don’t use the get method with OptionWhen you first come to Scala from Java, you may be tempted to use the  get method to
access the result:
scala> val x = toInt("5").get
x: Int = 5
However, this isn’t any better than a  NullPointerException :
scala> val x = toInt("foo").getjava.util.NoSuchElementException: None.get
// long stack trace omitted ...
Your next thought might be to test the value before trying to access it:
// don't do this
scala> val x = if (toInt("foo").isDefined) toInt("foo") else 0
x: Any = 0As the comment says, don’t do this. In short, it’s a best practice to never call  get on an
Option . The preferred approaches are to use  getOrElse , a match expression, or
foreach . (As with  null values, I just imagine that  get doesn’t exist.)

[scala基础]--Option/Some/None相关推荐

  1. 大数据入门第二十天——scala入门(二)scala基础02

    一. 类.对象.继承.特质 1.类 Scala的类与Java.C++的类比起来更简洁 定义: package com.jiangbei //在Scala中,类并不用声明为public. //Scala ...

  2. 23篇大数据系列(二)scala基础知识全集(史上最全,建议收藏)

    作者简介: 蓝桥签约作者.大数据&Python领域优质创作者.管理多个大数据技术群,帮助大学生就业和初级程序员解决工作难题. 我的使命与愿景:持续稳定输出,赋能中国技术社区蓬勃发展! 大数据系 ...

  3. Scala基础语法学习

    目录 一.变量 二.数据类型 三.scala中的条件表达式 四.循环 五.while循环 六.方法 6.函数 7.数组 (1).定长数组 (2).变长数组 (3).遍历数组 (4).数组常用操作 8. ...

  4. 【Spark】scala基础入门

    文章目录 零.IDEA的scala环境配置 0.1 spark和scala之间的关系 0.2 编写项目 (0)创建项目 (1)配置pom.xml文件: (2)配置对应环境 (3)测试代码 (4)控制台 ...

  5. Scala基础教程(六):字符串、数组、集合

    创建字符串: 最直接的方法来创建一个字符串的编写方法是: var greeting = "Hello world!"; or var greeting:String = " ...

  6. Scala基础教程(一):简介、环境安装

    Scala基础语法 如果有很好的了解Java语言,那么将很容易学习Scala. Scala和Java间的最大语法的区别在于;行结束符是可选的.考虑Scala程序它可以被定义为通过调用彼此方法进行通信的 ...

  7. Scala 基础(8)—— 占位符_和部分应用函数

    1. 占位符 _ 针对 Scala 基础(7)-- 函数字面量和一等函数 中最后提到的,关于 filter 函数字面量的精简写法,可以使用占位符 _ 来代替. 占位符_,用来表示一个或者多个参数.(这 ...

  8. Scala学习(一)--Scala基础学习

    Scala基础学习 摘要: 在篇主要内容:如何把Scala当做工业级的便携计算器使用,如何用Scala处理数字以及其他算术操作.在这个过程中,我们将介绍一系列重要的Scala概念和惯用法.同时你还将学 ...

  9. Scala基础教程--10--数组列表与函数式编程

    Scala基础教程–10–数组列表与函数式编程 章节目标 掌握数组, 元组相关知识点 掌握列表, 集, 映射相关知识点 了解迭代器的用法 掌握函数式编程相关知识点 掌握学生成绩单案例 1. 数组 1. ...

最新文章

  1. 监听指定端口数据交互(HttpListenerContext )
  2. kazoo源码分析:Zookeeper客户端start概述
  3. each 数据获取attr_调用高德POI数据,带你玩转长沙
  4. Android开发了解这些自然无惧面试,重难点整理
  5. 上海网络推广为大家讲解细节标签能给网站带来的作用与效果!
  6. 你选的那些创业方向 可能正在毁掉你!
  7. 计算机应用网站设计,《计算机应用基础》课程网站的设计与实现
  8. lcx源代码以及免杀的研究
  9. 从下往上看--新皮层资料的读后感 第一部分:皮层细胞
  10. Python 爬取 6000 篇文章分析 CSDN 是如何进入微信 500 强的
  11. 修改php.ini以达到 屏蔽错误信息
  12. 开启smb协议_SMB协议(使用说明+过程详解+抓包分析)
  13. (Word论文插入高清图片)软件设置教程
  14. 高斯消元求解四种方程组
  15. Chrome 浏览器小恐龙游戏变身超级马利奥
  16. 各代iphone尺寸_Iphone 历代 参数
  17. 在线工具网,程序员必备小网址
  18. Poj P3322 Bloxorz___bfs
  19. Java常用API——学习笔记(7)
  20. 70天攻克考研英语词汇-day1

热门文章

  1. flutter引入高德地图_玩玩Flutter Web —— 实现高德地图插件
  2. OpenCV~图像处理API(逆光、模糊、亮度、雾霾)
  3. c语言数论应用有关题目,中学数学中及初等数论相关的几个问题.docx
  4. 端子拉力测试标准汇总
  5. 首期“赛迪区块链技术与应用培训班”成功举办
  6. HDOJ2000题Java代码
  7. 单片机胡汉才第四版答案_单片机课后习题答案 胡汉才编
  8. Code里面的对立统一
  9. bochs安装以及使用
  10. 远控免杀专题(16)-Unicorn免杀(VT免杀率29/56)