【问题标题】:Map with two Key for a value?用两个键映射一个值?
【发布时间】:2012-06-03 00:14:54
【问题描述】:

我想创建一个有两个键的地图:

map.put (key1,key2,value1);// Insert into map
map.get(key1,key2); // return value1

我正在研究 multikeyMap,但我不知道该怎么做

【问题讨论】:

    标签: java data-structures map arraylist linked-list


    【解决方案1】:

    不幸的是,Java 不支持语言级别的元组,因此您必须使用像这里的一些答案中显示的那样的临时结构。这会导致大量的样板和代码重复。

    Functional Java 具有对元组的库支持。适合这里的类是P2。该名称的意思是“具有 2 个元素的产品”。 (产品只是复合类型的代数术语。)该库支持最多 8 个元素的元组。 P{n} 类覆盖所有必要的方法

    有一个名为P 的类,它提供了一个静态工厂方法p 用于构造元组。

    用法:

    import fj.P2;
    import fj.Ord;
    import fj.data.TreeMap;
    
    import static fj.Ord.*;
    import static fj.P.*;
    
    TreeMap<P2<Integer, String>, String> m = 
      TreeMap.<P2<Integer, String>, String>empty(p2Ord(intOrd, stringOrd)).
      set(p(1, "2"), "onetwo").
      set(p(5, "3"), "fivethree");
    

    【讨论】:

      【解决方案2】:

      如果您总是想通过 key1 和 key2 一起访问,您可以将它们与分隔符连接在一起作为键并使用法线贴图。

      【讨论】:

        【解决方案3】:

        如果您可以使用外部库,Guava 提供的正是 Table&lt;R, C, V&gt;,将两个键分别称为“行”和“列”。 (披露:我为 Guava 做出了贡献。)

        【讨论】:

          【解决方案4】:

          您可以考虑使用 Guava 的 Table 实现之一。来自文档:

          关联有序键对的集合,称为行键 和一个列键,只有一个值。一个表可能是稀疏的,有 只有一小部分行键/列键对拥有 对应的值。

          【讨论】:

            【解决方案5】:

            怎么样

            class Key{
             private final String key1;
             private final String key2;
            //accessors + hashcode + equals()
            }
            

            Map<Key, Value> map
            

            【讨论】:

              【解决方案6】:

              听起来您只需要一个由两个值创建的键。您可能会发现这两个值自然应该被封装到另一种类型中——或者您可以创建一个Key2&lt;K1, K2&gt; 类型。 (这里的命名允许Key3Key4 等。不过我不鼓励你走得太远。)

              对于介于两者之间的东西,您可以在真正需要的类中创建一个私有静态类(如果它只是一个内部实现细节)。如果它不是自然封装(例如,它类似于“名称和人口”,在此特定场景之外没有意义),那么在保留有意义的属性名称方面会很好,但不会公开。

              在任何这些情况下,您最终都会得到一个新类型,其中包含两个最终变量,它们在构造函数中初始化,并且对equalshashCode 都有贡献。例如:

              public final class Key2<K1, K2> {
                  private final K1 part1;
                  private final K2 part2;
              
                  public Key2(K1 part1, K2 part2) {
                      this.part1 = part1;
                      this.part2 = part2;
                  }
              
                  @Override public boolean equals(Object other) {
                      if (!(other instanceof Key2)) {
                          return false;
                      }
                      // Can't find out the type arguments, unfortunately
                      Key2 rawOther = (Key2) other;
                      // TODO: Handle nullity
                      return part1.equals(rawOther.part1) &&
                          part2.equals(rawOther.part2);
                  }
              
                  @Override public int hashCode() {
                      // TODO: Handle nullity
                      int hash = 23;
                      hash = hash * 31 + part1.hashCode();
                      hash = hash * 31 + part2.hashCode();
                      return hash;
                  }
              
                  // TODO: Consider overriding toString and providing accessors.
              }
              

              更多特定于情况的类型会稍微简单一些,因为它们不是通用的 - 特别是这意味着您无需担心类型参数,并且您可以为变量提供更好的名称。

              【讨论】:

                【解决方案7】:

                为什么不将 key 映射到 String 并连接 key1+key2

                【讨论】:

                • 在许多情况下,这不会很好地工作。例如,如果它们都是整数,则 1,11 最终与 11,1 相同 - 除非您开始添加分隔符等。就字符串表示而言,没有固有的调用我可以看到 - 在新类型中使用单独的字段会更干净。
                猜你喜欢
                • 1970-01-01
                • 2013-03-20
                • 1970-01-01
                • 1970-01-01
                • 2012-07-17
                • 2020-05-13
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多