I need a simple BiMap
implementation too so decided to create a little library called bimap
.
BiMap
的实现相当简单,但它包含一个棘手的部分,即一组条目、键和值.我将try 解释实现的一些细节,但是您可以在GitHub上找到完整的实现.
首先,我们需要为不可变和可变的BiMap
定义接口.
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?
}
Please, notice that BiMap.values
returns a Set
instead of a Collection
. Also BiMap.put(K, V)
throws an exception when the BiMap
already contains a given value. If you want to replace pairs (K1, V1)
and (K2, V2)
with (K1, V2)
you need to call forcePut(K, V)
. And finally you may get an inverse BiMap
to access its keys by values.
BiMap
使用两个常规 map 实现:
val direct: MutableMap<K, V>
val reverse: MutableMap<V, K>
The inverse BiMap
can be created by just swapping the direct
and the reverse
maps. My implementation provides an invariant bimap.inverse.inverse === bimap
but that's not necessary.
如前所述,forcePut(K, V)
方法可将线对(K1, V1)
和(K2, V2)
替换为(K1, V2)
.首先,它判断K1
的当前值,并将其从reverse
映射中删除.然后找到值V2
的键,并将其从direct
映射中移除.然后该方法将给定的对插入到两个映射中.下面是它在代码中的外观.
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
}
Implementations of Map
and MutableMap
methods are quite simple so I will not provide details for them here. They just perform an operation on both maps.
最复杂的部分是entries
、keys
和values
.在我的实现中,我创建了一个Set
,它将所有方法调用委托给direct.entries
,并处理条目的修改.每次修改都发生在try
/catch
块中,这样在抛出异常时BiMap
保持一致状态.此外,迭代器和可变项被包装在类似的类中.不幸的是,它使对条目的迭代效率大大降低,因为在每个迭代步骤上都会创建额外的MutableMap.MutableEntry
个包装器.