在不同对象上调用相同的方法时,返回类型不同

时间:2018-02-07 23:13:27

标签: scala collections

我写了以下申请:

  var counters: mutable.Map[String, mutable.Map[String, Long]] = mutable.Map()
  counters("key1") = mutable.Map("counters_key"→ 20)
  counters("key2") = mutable.Map("counters_key" → 920)
  counters("key3") = mutable.Map("counters_key" → 920)
  counters("key4") = mutable.Map("counters_key" → 920)
  counters("key5") = mutable.Map("counters_key" → 920)

  var counters2: mutable.Map[String, mutable.Map[String, Long]] = mutable.Map()
  counters2("key1") = mutable.Map("counters2_key_1"→ 112000, "counters_key_2" → 1112000, "counters_key_3"→ 20)
  counters2("key2") = mutable.Map("counters2_key_4" → 9112000, "counters_key_5" → 91112000, "counters_key_6" → 920)

  val flattenedCounters =  counters.toMap.values.flatten
  val flattenedCounters2 = counters2.toMap.values.flatten

  println(flattenedCounters.getClass == flattenedCounters2.getClass) 
  //true

  println(flattenedCounters.groupBy(_._1).getClass == 
          flattenedCounters2.groupBy(_._1).getClass) 
  //false

DEMO

我们在2个相同类型的对象上调用相同的方法。但它给了我们不同类型的对象。为什么?

2 个答案:

答案 0 :(得分:3)

密钥是计数器的大小

   val map = counters.toMap
   println(map.getClass)
   //class scala.collection.immutable.HashMap$HashTrieMap
   println(map.size)
   //5

   val map2 = counters2.toMap
   println(map2.getClass)
   //class scala.collection.immutable.Map$Map2
   println(map2.size)
   //2

看起来Scala有几个Map的实现。 Map2经过优化,可以准确保存2个元素。并且有优化的实施,最高可达Map4

您可以在sources

中找到这些课程

当您致电toMap时,它会创建一个包含空地图的新构建器。 然后为每个元素将其添加到地图中。

  • 空地图+新密钥是Map1 src
  • Map1 +新密钥是Map2 src
  • ...
  • Map4 +新密钥是HashMap src

答案 1 :(得分:1)

正如@Nazarii Bardiuk指出的那样,由于不可变地图大小的不同。 Scala通过将小地图存储为单个对象并将元素作为字段进行优化来优化小地图,并将HashMap更大的地图实现为使用HashTrieMap

来自相关Scala docHash Tries部分中的引用:

  

Scala进一步优化了不可变集和映射   包含少于五个元素。设置和映射一到四个   元素存储为仅包含元素的单个对象   (或地图中的键/值对)作为字段。