在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 })
时,会导致创建新地图的开销,我很乐意避免这种情况。
那么,这是设计吗?
答案 0 :(得分:2)
为什么?很难回答,但搜索或添加Kotlin issue tracker的故障单会获得答案,并在状态发生变化时更新您。由于toHashMap
存在toHashSet
,因此似乎缺少List
。(其中1.0 BETA 4)。
注意: LinkedHashMap是默认值,因为kotlin希望在从Set
到List
到Map
到{{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 } }