【问题标题】:Bidirectional Map双向地图
【发布时间】:2012-04-04 16:43:30
【问题描述】:

您能否推荐一种映射或类似的数据结构,我们可以在其中轻松地从彼此获取值和键。也就是说,每个都可以用来寻找另一个。

【问题讨论】:

标签: java dictionary


【解决方案1】:

基于此 QA 中的 this answer 及其 cmets,我编写了以下内容。 [将被测试]

双向地图

import java.util.HashMap;

public class BidirectionalMap<K, V> extends HashMap<K, V> {
private static final long serialVersionUID = 1L;
public HashMap<V, K> inversedMap = new HashMap<V, K>();

public K getKey(V value) {              
    return inversedMap.get(value);
}

@Override
public int size() {
    return this.size();
}

@Override
public boolean isEmpty() {
    return this.size() > 0;
}

@Override
public V remove(Object key) {
    V val=super.remove(key);
    inversedMap.remove(val);
    return val;
}

@Override
public V get(Object key) {
    return super.get(key);
}

@Override
public V put(K key, V value) {      
    inversedMap.put(value, key);
    return super.put(key, value);
}

}

【讨论】:

    【解决方案2】:

    您可以定义一个枚举并定义辅助方法来获取密钥。与 BidiMap 相比,性能要好得多。 例如

    public enum Fruit {
            APPLE("_apple");
            private final String value;
            Fruit(String value){
                this.value=value;
            }
            public String getValue(){
                return this.value;
            }
            public static String getKey(String value){
                Fruit fruits[] = Fruit.values();
                for(Fruit fruit : fruits){
                    if(value.equals(fruit.value)){
                        return fruit.name();
                    }
                }
                return null;        }
        }
    

    【讨论】:

      【解决方案3】:

      Java 在其标准库中没有双向映射。

      例如使用来自Google GuavaBiMap&lt;K, V&gt;

      【讨论】:

      • @Travis 谢谢,链接已更新。 (API 文档目前仍在 Google Code 上)。
      • 是的,我注意到他们也希望他们能搬到更安全的地方。
      • @Travis 他们都来自谷歌,所以他们可能不会搞砸自己的项目......
      • @Jesper - Google 可能需要 BiMap 用于特定用例。但是,为什么 Java 不提供 BiMap 呢?很高兴有数据结构和算法方面的选择,而不是从库中获取它们或从头开始编码。
      • @MasterJoe2 “为什么它不在标准库中”这个问题没有很好的答案。我们只能说:因为写标准库的人没有添加。
      【解决方案4】:

      Google Guava 包含一个BiMap(双向映射)。

      【讨论】:

      • 您应该更新链接以指向我要去的 Github,但认为这可能是微不足道的,因为当前链接现在有效。
      【解决方案5】:

      如果您觉得导入一些第三方库很痛苦。 这个简单的课程怎么样。

      public class BiMap<K,V> {
      
          HashMap<K,V> map = new HashMap<K, V>();
          HashMap<V,K> inversedMap = new HashMap<V, K>();
      
          void put(K k, V v) {
              map.put(k, v);
              inversedMap.put(v, k);
          }
      
          V get(K k) {
              return map.get(k);
          }
      
          K getKey(V v) {
              return inversedMap.get(v);
          }
      
      }
      

      确保 K 和 V 类具有正确的 hashCode 实现。

      【讨论】:

      • 问题是现在这不是一个集合,所以所有的集合方法都不起作用。
      • 真的。我最终添加了我需要的东西
      • 嗯,这个 BiMap 方法可以实现 Map 对吧?然后它就变成了一个集合。
      • 不是一个干净的方式imo。它必须是组合而不是继承的情况
      • 您可以从HashMap 扩展并在内部保留一个反转映射。然后覆盖所有进行突变的方法,并通过值添加相应的方法进行检索。
      【解决方案6】:

      对于需要这样的字典的一般用例,我认为 KISS 解决方案没有任何问题,只需将键和值反之亦然,节省第二个 Map 甚至为此目的的库的开销:

      myMap.put("apple", "Apfel");
      myMap.put("Apfel", "apple");
      

      【讨论】:

      • 请注意,这只有在 key 和 value 是相同类型的情况下才有效,并且您将不再知道哪个是 key 哪个是 value。在某些情况下这可能很好。
      【解决方案7】:

      也可以试试 Apache Commons Collections 4 BidiMap 包。

      【讨论】:

        【解决方案8】:

        最常见的解决方案是使用两张地图。您可以通过扩展AbstractMap 轻松地将它们封装在具有友好接口的类中。 (更新:这就是 Guava 的 HashBiMap 的实现方式:两张地图)

        只使用数组和自定义类来创建新的数据结构几乎没有什么优势。映射实现是索引键的数据结构的轻量级包装器。由于您需要两个索引,因此您不妨使用两个完整的地图。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-23
          相关资源
          最近更新 更多