scala flatMap为何能过滤掉Option中的None

-------------------------------------------------------------------------
*************************************************************************
-------------------------------------------------------------------------
import scala.collection.mutable._
def indexes(a: Array[String], m: Map[String,Int]) = a.flatMap(m.get(_))
def indexes1(a: Array[String], m: Map[String,Int]) = a.map(m.get(_))
val am = Array("Tom", "Fred", "Harry")
val m1 = Map("Dick" -> 4)


调用这俩个方法:

val inamm=indexes(am,m1)
inamm.foreach(print(_))
println
val inamm1=indexes1(am,m1)
inamm1.foreach(print(_))

输出结果:

3
Some(3)NoneNone

-------------------------------------------------------------------------
*************************************************************************
-------------------------------------------------------------------------

很好奇为什么能过滤掉None,请教了scala中国群里的kerr、林晴、wxk、小星心等人,总结如下:

(1) m.get(_)的返回类型是Option[Int],这个好理解;源码中Option.class中有这样的隐式转换:

implicit def option2Iterable[A](xo: Option[A]): Iterable[A] = xo.toList

toList的定义如下:
def toList: List[A] =
  if (isEmpty) List() else new ::(this.get, Nil)
所以是转换为了List(2)或者List(),注意List(2)是单例List,即仅仅有一个元素。
-----------------------------------------
-----------------------------------------
(2)再看flatMap的源码(在Idea里面,按住Ctrl,然后鼠标点进去,即可看到调用的源码)
//这里是TraversableLike.class中
def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
  def builder = bf(repr) // extracted to keep method size under 35 bytes, so that it can be JIT-inlined
  val b = builder
  for (x <- this) b ++= f(x).seq
  b.result
}
注意代码实现部分主要与bf有关,在点进去看bf的实现:
-----------------------------------------
-----------------------------------------
trait CanBuildFrom[-From, -Elem, +To] {

  /** Creates a new builder on request of a collection.
   *  @param from  the collection requesting the builder to be created.
   *  @return a builder for collections of type `To` with element type `Elem`.
   *          The collections framework usually arranges things so
   *          that the created builder will build the same kind of collection
   *          as `from`.
   */
  def apply(from: From): Builder[Elem, To]
显然是调用了apply(from:From),点进去Builder:
-----------------------------------------
-----------------------------------------
import generic._

/** The base trait of all builders.
 *  A builder lets one construct a collection incrementally, by adding
 *  elements to the builder with `+=` and then converting to the required
 *  collection type with `result`.
 *
 *  @tparam  Elem  the type of elements that get added to the builder.
 *  @tparam  To    the type of collection that it produced.
 *
 *  @since 2.8
 */
trait Builder[-Elem, +To] extends Growable[Elem] {

  /** Adds a single element to the builder.
   *  @param elem the element to be added.
   *  @return the builder itself.
   */
从英文部分可得到下面的naive interpretation
-----------------------------------------
-----------------------------------------
implicit bf: CanBuildFrom[Repr, B, That],它这个是先让this.asInstanceOf(Repr),然后逐个添加元素B,最后返回结果That。
即它是要求输入数据是Repr,添加这个集合中的数据是B,这个集合的result()方法返回的是That类型.

-----------------------------------------
-----------------------------------------
(3) 正是bf++=f(x).seq,f(x)是List,List中++是可以过滤掉List()的。

至此,对题目中的问题做了一个粗略的分析,由于是初学者,以后再慢慢清晰化。

有问题请及时留言或者发送邮件到zhanghao_study@163.com.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值