再说Map,Map里面的value的类型并不是你赋的那个数据类型,而是Option。即Map(key -> Option,key1 -> Option)。
scala> val map = Map("test1" -> 1,"test2" -> 2)
map: scala.collection.immutable.Map[String,Int] = Map(test1 -> 1, test2 -> 2)
scala> map.get("test1")
res16: Option[Int] = Some(1)
scala> map.get("test3")
res17: Option[Int] = None
scala> map.get("test3").getOrElse("this is null")
res18: Any = this is null
这样的好处是什么呢?还记得在java里面,每次都得为java为空的情况做判断的痛苦吗。在scala,这些烦恼通通不存在。有了Option,妈妈再也不用担心NullPointerException啦。
1.4 常用函数组合子
匿名函数
将集合的函数组合子,那肯定得先将匿名函数。如果有用过python中的lambda表达式,那应该就很了解这种方式了。
前面说到,在scala中,函数就是对象,匿名函数也是函数。举个简单的例子:
//创建一个匿名函数 scala> val addOne = (x: Int) => x + 1 addOne: (Int) => Int = <function1> scala> addOne(1) res4: Int = 2
注意,函数里面是可以不用return的,最后面的那个x+1就是匿名函数的返回值了。
map,reduce
因为hadoop的出现,MapReduce都被说烂了。虽然Hadoop的Mapreduce起源自函数式的map和reduce,但两者其实是不一样的。感兴趣的可以看看我之前写过的一篇:从分治算法到 Hadoop MapReduce
函数式里面的map呢,粗略的说,其实相当一个有返回值的for循环。
scala> val list = List(1,2,3) list: List[Int] = List(1, 2, 3) scala> list.map(_ + 1) //这里的(_+1)其实就是一个匿名函数 //让List中每一个元素+1,并返回 res29: List[Int] = List(2, 3, 4)
至于reduce呢,也是像for循环,只是不像map每次循环是当前元素,reduce除了当前元素,还有上一次循环的结果,还是看看例子吧:
scala> list.reduce((i,j) => i + j) //两个两个一起循环,这里是让两个相加 res28: Int = 6
比如上面的例子,有1,2,3三个数。第一次循环的两个是1,2,1+2就等于3,第二次循环就是上次的结果3和原本的3,3+3等于6,结果就是6。
filter
filter故名思意,就是过滤的意思,可以在filter中传进去一个匿名函数,返回布尔值。返回true的则保留,返回false的丢弃。
scala> val numbers = List(1, 2, 3, 4) numbers: List[Int] = List(1, 2, 3, 4) //过滤出余2等于0的 scala> numbers.filter((i: Int) => i % 2 == 0) res0: List[Int] = List(2, 4)
foldLeft
这个和reduce类似,也是遍历,除了当前元素,还有上一次迭代的结果。区别在于foldLeft有一个初始值。
scala> val numbers = List(1, 2, 3, 4) numbers: List[Int] = List(1, 2, 3, 4) //(m: Int, n: Int) => m + n这部分是一个匿名函数 scala> numbers.foldLeft(0)((m: Int, n: Int) => m + n) res30: Int = 10









