如何构建Scala地图?

时间:2016-09-29 03:49:29

标签: scala

Scala可以使用不同的Map实例化不同大小的Map实例。结果,

val l = List("a", "b", "c", "d", "e", "f", "g")

val ms = l.zipWithIndex map {
  case (e, i) => l.take(i).zipWithIndex.toMap /// toMap
}

ms.foreach(m => println(m.getClass))

会发出:

class scala.collection.immutable.Map$EmptyMap$
class scala.collection.immutable.Map$Map1
class scala.collection.immutable.Map$Map2
class scala.collection.immutable.Map$Map3
class scala.collection.immutable.Map$Map4
class scala.collection.immutable.HashMap$HashTrieMap
class scala.collection.immutable.HashMap$HashTrieMap

(上面的代码由toMap生成,但使用apply非常相似。)

我发现toMap被定义为

  def toMap[T, U](implicit ev: A <:< (T, U)): immutable.Map[T, U] = {
    val b = immutable.Map.newBuilder[T, U]
    for (x <- self)
      b += x

    b.result()
  }

魔术部分将是result()的{​​{1}},因为它最终确定应该实例化哪个Map子类。

Builder内,有object MapEmptyMapMap1Map2Map3Map4object HashMap;另外,两者都包含隐式HashTrieMap

那么Scala编译器如何确定将哪个子类用于Map?

(此问题可能更多关于MapCanBuildFrom,例如,CanBuildFrom会实例化Seq(1)。)

1 个答案:

答案 0 :(得分:6)

我在scala库中偷看,似乎对Map的这4个特定impl的唯一引用是在他们自己的“更新”和“ - ”方法中。 魔术从方法newBuilder中的MutableMapFactory开始,其中调用Map.empty来生成EmptyMap类。 然后调用更新并添加键和值将使其成为Map1。然后再次调用Map1中的更新方法可以导致Map1或Map2,并且调用 - 方法可以导致EmptyMap。等...

y