多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
### null 的问题 ~~~ Map<String, String> map = ??? String valFor2014 = map.get(“1024”); // null if (valFor1024 == null) abadon(); 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 ~~~ def get(key: A): Option[B] def getOrElse[B1 >: B](key: A, default: => B1): B1 = get(key) match { case Some(v) => v case None => default } ~~~ * 可以区分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](http://www.scala-lang.org/api/2.11.7/index.html#scala.Option) ### 试试容器里的各种方法 ~~~ val a: Option[String] = Some("1024") val b: Option[String] = None a.map(_.toInt) //res0: Option[Int] = Some(1024) b.map(_.toInt) //res1: Option[Int] = None,不会甩exception a.filter(_ == "2048") //res2: Option[String] = None b.filter(_ == "2048") //res3: Option[String] = None a.getOrElse("2048") //res4: String = 1024 b.getOrElse("2048") //res5: String = 2048 a.map(_.toInt) .map(_ + 1) .map(_ / 5) .map(_ / 2 == 0) //res6: Option[Boolean] = Some(false) //如果是null,恐怕要一连check abandon四遍了 ~~~ ### option配合其他容器使用 ~~~ 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) ~~~ * option帮助你把错误扼杀在编译阶段 * flatMap则可以在过滤空值的同时将option恢复为原始数据. scala原生容器类都对option有良好支持 ~~~ Seq(1,2,3).headOption //res0: Option[Int] = Some(1) Seq(1,2,3).find(_ == 5) //res1: Option[Int] = None Seq(1,2,3).lastOption //res2: Option[Int] = Some(3) Vector(1,2,3).reduceLeft(_ + _) //res3: Int = 6 Vector(1,2,3).reduceLeftOption(_ + _) //res4: Option[Int] = Some(6) //在vector为空的时候也能用 Seq("a", "b", "c", null, "d").map(Option(_)) //res0: Seq[Option[String]] = // List(Some(a), Some(b), Some(c), None, Some(d)) //原始数据转换成option也很方便 ~~~