Kotlin是否有双向哈希图?
如果不是,用kotlin表达这一点的最佳方法是什么?
包括 Guava 以从那里获取BiMap感觉就像用非常大的枪在很小的目标上射击-我目前无法想象的解决方案感觉正确-我想到的最好的事情就是为它编写一个自定义类
最佳答案
我也需要一个简单的BiMap
实现,因此决定创建一个名为 bimap
的小库。BiMap
的实现非常简单,但是它包含一个棘手的部分,它是一组条目,键和值。我将尝试解释实现的一些细节,但是您可以在GitHub上找到完整的实现。
首先,我们需要为不可变和可变的BiMap
定义接口(interface)。
interface BiMap<K : Any, V : Any> : Map<K, V> {
override val values: Set<V>
val inverse: BiMap<V, K>
}
interface MutableBiMap<K : Any, V : Any> : BiMap<K, V>, MutableMap<K, V> {
override val values: MutableSet<V>
override val inverse: MutableBiMap<V, K>
fun forcePut(key: K, value: V): V?
}
请注意,
BiMap.values
返回的是Set
而不是Collection
。当BiMap.put(K, V)
已经包含给定值时,BiMap
也会引发异常。如果要将(K1, V1)
和(K2, V2)
对替换为(K1, V2)
,则需要调用forcePut(K, V)
。最后,您可能会得到一个反向BiMap
,以按值访问其键。BiMap
使用两个常规映射实现:val direct: MutableMap<K, V>
val reverse: MutableMap<V, K>
可以通过交换
BiMap
和direct
映射来创建反reverse
。我的实现提供了一个不变的bimap.inverse.inverse === bimap
,但这不是必需的。如前所述,
forcePut(K, V)
方法可以将对(K1, V1)
和(K2, V2)
替换为(K1, V2)
。首先,它检查K1
的当前值是什么,并将其从reverse
映射中删除。然后,它找到值V2
的键并将其从direct
映射中删除。然后,该方法将给定对插入到两个 map 中。这是它在代码中的外观。override fun forcePut(key: K, value: V): V? {
val oldValue = direct.put(key, value)
oldValue?.let { reverse.remove(it) }
val oldKey = reverse.put(value, key)
oldKey?.let { direct.remove(it) }
return oldValue
}
Map
和MutableMap
方法的实现非常简单,因此在此不再赘述。他们只是在两个 map 上执行操作。最复杂的部分是
entries
,keys
和values
。在我的实现中,我创建了一个Set
,它将所有方法调用委托(delegate)给direct.entries
并处理条目的修改。每种修改都在try
/catch
块中进行,以便在引发异常时BiMap
保持一致状态。而且,迭代器和可变条目被包装在类似的类中。不幸的是,由于在每个迭代步骤上都会创建一个附加的MutableMap.MutableEntry
包装器,因此它会使条目的迭代效率大大降低。关于kotlin - Kotlin中的BiMap/2路哈希图,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36373760/