加载中...

用 option 代替 null


null 的问题

  1. Map<String, String> map = ???
  2. String valFor2014 = map.get(“1024”); // null
  3. if (valFor1024 == null)
  4. abadon();
  5. else doSomething();
  • null到底代表key找不到还是说1024对应的值就是null?
  • 某年某月某日,我把为null则abandon这段代码写了100遍.

option介绍

  • option可以看作是一个容器,容器的size是1或0
  • Size为1的时候就是一个Some[A](x: A),size为0的时候就是一个None

看看scala的map

  1. def get(key: A): Option[B]
  2. def getOrElse[B1 >: B](key: A, default: => B1): B1 = get(key) match {
  3. case Some(v) => v
  4. case None => default
  5. }
  • 可以区分Map中到底又没有这个key.
  • 我见过许多java项目自己实现了getOrElse这个方法并放在一个叫做MapUtils的类里.
  • 为什么java经过这么多代演进,Map仍然没有默认包含这个方法,一直想不通.
    (写完这段突然发现java8开始包含getOrDefault了)

好像没有太大区别?

确实能够区分Map是无值还是值为null了.
但是if(为null) 则 abandon 要写一百遍.
case Some(v) => v
case None => default
似乎也得写一百遍.

不,不是这样的
不要忘了option是个容器
http://www.scala-lang.org/api/2.11.7/index.html#scala.Option

试试容器里的各种方法

  1. val a: Option[String] = Some("1024")
  2. val b: Option[String] = None
  3. a.map(_.toInt)
  4. //res0: Option[Int] = Some(1024)
  5. b.map(_.toInt)
  6. //res1: Option[Int] = None,不会甩exception
  7. a.filter(_ == "2048")
  8. //res2: Option[String] = None
  9. b.filter(_ == "2048")
  10. //res3: Option[String] = None
  11. a.getOrElse("2048")
  12. //res4: String = 1024
  13. b.getOrElse("2048")
  14. //res5: String = 2048
  15. a.map(_.toInt)
  16. .map(_ + 1)
  17. .map(_ / 5)
  18. .map(_ / 2 == 0) //res6: Option[Boolean] = Some(false)
  19. //如果是null,恐怕要一连check abandon四遍了

option配合其他容器使用

  1. val a: Seq[String] =
  2. Seq("1", "2", "3", null, "4")
  3. val b: Seq[Option[String]] =
  4. Seq(Some("1"), Some("2"), Some("3"), None, Some("4"))
  5. a.filter(_ != null).map(_.toInt)
  6. //res0: Seq[Int] = List(1, 2, 3, 4)
  7. //如果你忘了检查,编译器是看不出来的,只能在跑崩的时候抛异常
  8. b.flatMap(_.map(_.toInt))
  9. //res1: Seq[Int] = List(1, 2, 3, 4)
  • option帮助你把错误扼杀在编译阶段
  • flatMap则可以在过滤空值的同时将option恢复为原始数据.

scala原生容器类都对option有良好支持

  1. Seq(1,2,3).headOption
  2. //res0: Option[Int] = Some(1)
  3. Seq(1,2,3).find(_ == 5)
  4. //res1: Option[Int] = None
  5. Seq(1,2,3).lastOption
  6. //res2: Option[Int] = Some(3)
  7. Vector(1,2,3).reduceLeft(_ + _)
  8. //res3: Int = 6
  9. Vector(1,2,3).reduceLeftOption(_ + _)
  10. //res4: Option[Int] = Some(6)
  11. //在vector为空的时候也能用
  12. Seq("a", "b", "c", null, "d").map(Option(_))
  13. //res0: Seq[Option[String]] =
  14. // List(Some(a), Some(b), Some(c), None, Some(d))
  15. //原始数据转换成option也很方便

还没有评论.