Java是否有反向查找的HashMap?

Kip*_*Kip 95 java hashmap map bidirectional reverse-lookup

我的数据是以"密钥"格式组织的,而不是"键值".它就像一个HashMap,但我需要在两个方向上进行O(1)查找.这种类型的数据结构是否有名称,Java标准库中是否包含这样的名称?(或者可能是Apache Commons?)

我可以编写自己的类,基本上使用两个镜像映射,但我宁愿不重新发明轮子(如果这已经存在但我只是没有找到合适的术语).

uck*_*man 105

Java API中没有这样的类.您想要的Apache Commons类将成为BidiMap的一个实现.

作为一名数学家,我将这种结构称为双射.

  • 作为一个非数学家,我会把这种结构称为"一个地图,它可以让你通过键或其他方式查找值" (80认同)
  • 太糟糕了,它不支持泛型,似乎番石榴确实如此. (4认同)
  • https://github.com/megamattron/collections-generic具有支持泛型的BidiMap (2认同)
  • @Dónal是的,但整个IT都是基于数学的 (2认同)

Col*_*inD 73

除了Apache Commons之外,Guava还有一个BiMap.

  • Google Collections的一个优点是它具有泛型,而Commons Collections则没有. (16认同)
  • 有关两个库的比较,请参阅此答案中的引号:http://stackoverflow.com/questions/787446/is-there-a-java-1-5-equivalent-to-the-predicatet-methods-in- net/787459#787459(和原访谈).由于显而易见的原因,这对谷歌有偏见,但即便如此,我认为现在说你最好使用谷歌收藏也是安全的. (3认同)

GET*_*Tah 19

这是一个我用来完成这个的简单类(我不想再有另一个第三方依赖).它不提供地图中提供的所有功能,但它是一个良好的开端.

    public class BidirectionalMap<KeyType, ValueType>{
        private Map<KeyType, ValueType> keyToValueMap = new ConcurrentHashMap<KeyType, ValueType>();
        private Map<ValueType, KeyType> valueToKeyMap = new ConcurrentHashMap<ValueType, KeyType>();

        synchronized public void put(KeyType key, ValueType value){
            keyToValueMap.put(key, value);
            valueToKeyMap.put(value, key);
        }

        synchronized public ValueType removeByKey(KeyType key){
            ValueType removedValue = keyToValueMap.remove(key);
            valueToKeyMap.remove(removedValue);
            return removedValue;
        }

        synchronized public KeyType removeByValue(ValueType value){
            KeyType removedKey = valueToKeyMap.remove(value);
            keyToValueMap.remove(removedKey);
            return removedKey;
        }

        public boolean containsKey(KeyType key){
            return keyToValueMap.containsKey(key);
        }

        public boolean containsValue(ValueType value){
            return keyToValueMap.containsValue(value);
        }

        public KeyType getKey(ValueType value){
            return valueToKeyMap.get(value);
        }

        public ValueType get(KeyType key){
            return keyToValueMap.get(key);
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 您将通过将containsValue()更改为返回valueToKeyMap.containsKey(value)来显着提高containsValue()的性能 (5认同)

rsp*_*rsp 11

如果没有发生冲突,您可以随时将两个方向添加到同一个HashMap :-)

  • 不,这是一个丑陋,脆弱的黑客.它需要在每个get()和put()上维护双向属性,并且可以将其传递给修改地图的其他方法,甚至不需要知道双向属性.也许它可以作为一个局部变量在一个方法中没有被传递到任何地方,或者如果它在创建后立即变得不可修改.但即便如此,它也很脆弱(有人出现并调整功能并以一种不会立即显示自身成为问题的方式打破双向性) (7认同)
  • @Kip:为什么?在某些情况下,这是一个完全合法的解决方案.那么将有两个哈希映射. (6认同)
  • 完全是一个黑客. (3认同)

Ful*_*ius 7

这是我的 2 美分。

或者您可以使用带有泛型的简单方法。小菜一碟。

public static <K,V> Map<V, K> invertMap(Map<K, V> toInvert) {
    Map<V, K> result = new HashMap<V, K>();
    for(K k: toInvert.keySet()){
        result.put(toInvert.get(k), k);
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

当然,您必须拥有具有唯一值的地图。否则,其中之一将被替换。