【问题标题】:Multiple Keys to Single Value Map Java单值映射 Java 的多个键
【发布时间】:2011-10-09 18:48:39
【问题描述】:

我认为我的问题与此类似:How to implement a Map with multiple keys?,但有一个重要区别。在那个问题中(如果我对它的理解是正确的,如果不是,请告诉我),密钥应该始终是唯一的。我想有一个形式的地图: 我的地图 其中键不一定是唯一的。如果这没有意义,我基本上想要一个二维数组,但不是通过坐标来引用元素,我想通过成对的对象来引用它们。

任何人对可以使用的库或自己实现它的好方法有任何想法吗?就图书馆而言,我看过 Apache Commons 和 Guava,似乎都没有我想要的。

【问题讨论】:

  • 好吧,map 的整个概念是唯一的 Key->value 对,想要打破这个概念表明您应该使用与第一步不同的存储对象。你能举一个“通过成对的对象引用[元素]”的例子吗?这可能对我有帮助。
  • 你看过 Guava 库中的 MultiMap 吗?
  • 我看过MultiMap,这不是我想要的。您提出了一个很好的观点,即我想要的不是地图,我将研究下面答案中提到的表结构,这是我没见过的。但是要回答您的问题,就像您通过以下方式引用原始二维数组中的元素一样:array[0][1],我希望能够做到:array[obj1][obj2] 并拥有该映射到一个值(显然使用不同的语法,这正是我想要的功能)。
  • 在常规地图中使用stackoverflow.com/questions/156275/… 对?

标签: java data-structures map multidimensional-array


【解决方案1】:

Guava 中的Table 数据结构似乎可以满足您通过一对对象引用一个值的要求。

【讨论】:

  • 但是只为Table数据结构添加Guava lib是不值得的,因为它有大约15000个方法,所有这些都没有用。
【解决方案2】:

在我看来,您正在寻找一个嵌套的 HashMap。这可能会奏效,但我的直觉是,实现这样一个怪物将是一个糟糕的想法,无论是在性能方面还是在理智方面。

如何初始化它:

    HashMap<Key1, HashMap<Key2, Value>> nestedHashMap = new HashMap<Key1, HashMap<Key2, Value>>();

添加值:

    Key1 first;
    Key2 second;
    Value data;
    HashMap<Key2, Value> tempMap = new HashMap<Key2, Value>();
    tempMap.put(second, data);
    nestedHashMap.put(first, tempMap);

取回数据:

    Key1 first;
    Key2 second;
    Value data;
    data = nestedHashMap.get(first).get(second);

免责声明:此代码未经测试,只是从我的脑海中浮现出来。

【讨论】:

    【解决方案3】:

    我希望这个答案不会被视为咆哮,但据我所知,您希望使用库来实现您可以使用开箱即用的 jdk 以微不足道的方式实现的目标。

    无论如何,您提到要使用一对对象访问元素。您可以创建一个类来保存密钥,例如

    public class Pair {
      // string represntation of an object
      private final String x; 
      private final String y;
    
      // ctor, getters...
    
      public int hashcode() {...}
      public boolean equals(Object other) {...}
    }
    

    hashcode 方法将为所有组成元素生成哈希码(在这种情况下,两个,xy 在您的情况下,但可以轻松扩展以支持任意数量的元素),以及两个如果 xy 的值相同,则密钥将相同。如果您的 pair 元素不是简单的字符串,那么派生几乎任何对象的字符串表示是微不足道的(例如,提供toString 方法的体面实现)。

    这个想法是为对中的每个元素提供一个唯一的字符串表示。

    当然,生成可靠的哈希码并非易事,因此使用字符串是一个很好的选择。要生成哈希码,您只需附加对对象的字符串表示:

    public int hashcode() {
      return ('x' + x + ":y" + y).hashcode();
    }
    

    一定要提供一些分隔符。否则,对于x=ab, y=bx=a, y=bb 等值,即使对象完全不同,您也会得到相同的哈希码。

    而相等性就像检查对中元素的值一样微不足道:

    public boolean equals(Object other) {
      // if other is not null and is an instance of Pair
      final Pair otherPair = (Pair)other;
      return this.x.equals(otherPair.x) && this.y.equals(otherPair.y);
    }
    

    所以,现在您可以在地图中使用您的Pairclass,例如:

    final Map<Pair, Whatever> map = new Hashmap<Pair, Whatever>();
    // ...
    

    基本上,hashmap 通过使用键的哈希码来确定应该在哪个桶中分配值。如果两个键具有相同的哈希码,那么将使用 equals 方法来确定是刚刚发生冲突,还是只是 same 键。

    如果您想在TreeMap 中使用您的Pair 类,则必须实现compareTo 方法,或者在实例化此类映射时提供您自己的ComparatorTreeMap 实现依赖于 compareTo 方法的结果来确定应该在哪里分配值。

    【讨论】:

    • 我接受的答案是建议使用下面的 Guava Table 类,因为这似乎比编写/测试/调试我自己的自定义数据结构更容易。但是 - 仍然赞成同样出色的解决方案,谢谢。
    • equals 和 override 方法对我不起作用。我使用了eclipse生成的方法,效果很好。 Source > 生成 hashCode() 和 equals()。
    • 给予 +1 是因为......“我希望这个答案不会被视为咆哮”
    【解决方案4】:

    Apache Commons Collections 有 MultiKey

    import org.apache.commons.collections4.keyvalue.MultiKey;
    
    Map<MultiKey, ValueType> myMap = new HashMap<MultiKey, ValueType>();
    myMap.put(new MultiKey(key1, key2), value);
    
    myMap.get(new MultiKey(key1, key2));
    

    它具有从 Map 创建 N 维数组的好处。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-22
      • 2013-03-12
      • 1970-01-01
      • 1970-01-01
      • 2020-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多