Kotlin地图:为什么没有toHashMap()?

时间:2015-11-04 21:54:02

标签: kotlin

在Kotlin中,Map班级有toLinkedMap()toSortedMap()个扩展方法。

但为什么没有toHashMap()方法呢?事实上,许多stdlib方法的最终Map实现是LinkedHashMap,但是在我的代码中将其转换为HashMap会让我依赖于实现,这是不好的。

引入这样的方法可以使开发人员免于深入挖掘实现,并且使用当前的实现,它只会执行强制转换。

我的用例是:

val matchesInClass: HashMap<MessageClass, HashMap<Int, Int>>

//...

for ((cl, matches) in matchesInClass) {
    matchesInClass[cl] = matches.filterKeys { it !in banned } //error: not a HashMap
}

当我使用HashMap(matches.filterKeys { it !in banned })时,会导致创建新地图的开销,我很乐意避免这种情况。

那么,这是设计吗?

4 个答案:

答案 0 :(得分:2)

为什么?很难回答,但搜索或添加Kotlin issue tracker的故障单会获得答案,并在状态发生变化时更新您。由于toHashMap存在toHashSet,因此似乎缺少List。(其中1.0 BETA 4)。

注意: LinkedHashMap是默认值,因为kotlin希望在从SetListMap到{{1}时保持元素的顺序到List并确保事情仍处于相对顺序。

无论如何,在此期间,这里有一个自定义toHashMap

public fun <K, V> Iterable<Pair<K, V>>.toHashMap(): Map<K, V>
    = HashMap<K, V>(collectionSizeOrNull() ?: 16).apply { putAll(this@toHashMap) }

您可以通过使用类似于toMap函数的逻辑来选择最佳初始地图大小,或者不设置它并信任默认增长实现,从而使其更好。

Kotlin可轻松扩展。如果将所有内容放入stdlib中,那么受限设备(例如Android)上的人会抱怨它太大了,而且人们要求的大部分内容都是小怪,只需几行代码放入您自己的自定义库中。

答案 1 :(得分:1)

我同意stdlib中的这个地方不方便。但是,您希望如何实现这样的函数toHashMap()

如果底层映射是HashMap,则最简单的实现会使转换as HashMap生成,否则转换它。因此,在更改实现的情况下,该代码的性能将发生巨大变化。那很糟糕。

所以,恕我直言,我更喜欢不安全的演员表,如果stdlib以一种奇怪的方式发生变化而失败,并提醒我。

无论如何,我们随时欢迎您将此问题报告为YouTrack http://youtrack.jetbrains.com/issues/KT中的故障单。你在这里给出了一个很好的描述问题的描述,所以不应该花很长时间。

答案 2 :(得分:1)

这不是您原始问题的答案,而是您的用例的替代解决方案。

在这里,您尝试过滤HashMap<Int, Int>并将其分配回原来的地图:

  

matchesInClass [cl] = matches.filterKeys {it!in banned} //错误:不是HashMap

如果您没有要求保持matches HashMap完整,您可以通过在其removeAll可变集上调用keys函数来就地过滤它:

val matchesInClass: HashMap<MessageClass, HashMap<Int, Int>>

//...

for (matches in matchesInClass.values) {
    matches.keys.removeAll { it in banned } // notice the inverted condition
}

这比创建过滤后的副本更有效。

另一种选择是使用Map.filterTo提供所需类型的空地图:

for (entry in matchesInClass) {
    entry.setValue(entry.value.filterTo(HashMap()) { it !in banned })
}

答案 3 :(得分:0)

如何过滤它:

val filtered = matchesInClass.mapValues { it.value.filterKeys { it !in banned } }