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>

可以通过交换BiMapdirect映射来创建反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
}
MapMutableMap方法的实现非常简单,因此在此不再赘述。他们只是在两个 map 上执行操作。

最复杂的部分是entrieskeysvalues。在我的实现中,我创建了一个Set,它将所有方法调用委托(delegate)给direct.entries并处理条目的修改。每种修改都在try/catch块中进行,以便在引发异常时BiMap保持一致状态。而且,迭代器和可变条目被包装在类似的类中。不幸的是,由于在每个迭代步骤上都会创建一个附加的MutableMap.MutableEntry包装器,因此它会使条目的迭代效率大大降低。

关于kotlin - Kotlin中的BiMap/2路哈希图,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36373760/

10-09 01:13