【问题标题】:Howto Store 2 combined unique key in a HashMap?如何在 HashMap 中存储 2 个组合唯一键?
【发布时间】:2012-09-28 06:51:49
【问题描述】:

我想存储绑定到名称 + 数字的值。 比如,(John,1) (RED) and (John,2) (BLUE) and (Elize,1) (GREEN) 那么我怎样才能存储组合唯一的 2 个键呢?

【问题讨论】:

    标签: java hashmap key-value unique-key


    【解决方案1】:

    创建一个表示复合键的新类型(此处为名称和数字)。您需要覆盖hashCode()equals(),我强烈建议您将类型设置为不可变。例如:

    public final class NameIntPair {
        private final int intValue;
        private final String name;
    
        public NameIntPair(int intValue, String name) {
            this.intValue = intValue;
            this.name = name;
        }
    
        @Override
        public int hashCode() {
            int hash = 17;
            hash = hash * 31 + intValue;
            hash = hash * 31 + (name == null ? 0 : name.hashCode());
            return hash;
        }
    
        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof NameIntPair)) {
               return false;
            }
            if (this == obj) {
               return true;
            }
            NameIntPair other = (NameIntPair) obj;
            return other.intValue == intValue && Objects.equal(other.name, name);
        }
    }
    

    为了方便起见,我使用 Guava 中的 Objects.equal 来避免显式的无效性检查 - 如果您不使用 Guava,则必须在代码中使用等效项或处理无效性。或者,您可能希望防止空名称,在构造函数中验证它。

    【讨论】:

    • 谢谢,但我从来没有在 HashMap 中使用过 hashcode/equals,你能举个例子,我怎样才能得到 John,1 的值吗?
    【解决方案2】:

    如果我确定组合的唯一性并且键对象易于字符串化,我将使用字符串连接。我可能会使用特殊字符来连接键(如“John#1”和“John#2”)。

    如果我不确定,我会使用Guava's Table

    通常,当您尝试索引多个键时 时间,你会得到类似 Map(FirstName, Map(LastName, Person)),使用起来丑陋且尴尬。番石榴 提供了一个新的集合类型 Table,它支持这个用例 对于任何“行”类型和“列”类型

    所以表是

    关联有序键对的集合,称为行键 和一个列键,只有一个值。

    【讨论】:

      【解决方案3】:

      像这样定义您的特定 Key 类:

      public class Key {
          final String name;
          final int number;
          public Key(String name, int number) {
              this.name = name;
              this.number = number;
          }
          @Override
          public int hashCode() {
              final int prime = 31;
              int result = 1;
              result = prime * result + getOuterType().hashCode();
              result = prime * result
                      + ((name == null) ? 0 : name.hashCode());
              result = prime * result + number;
              return result;
          }
          @Override
          public boolean equals(Object obj) {
              if (this == obj)
                  return true;
              if (obj == null)
                  return false;
              if (getClass() != obj.getClass())
                  return false;
              Key other = (Key) obj;
              if (!getOuterType().equals(other.getOuterType()))
                  return false;
              if (name == null) {
                  if (other.name != null)
                      return false;
              } else if (!name.equals(other.name))
                  return false;
              if (number != other.number)
                  return false;
              return true;
          }
          private Test getOuterType() {
              return Test.this;
          }
       }
      

      重要的一点是确保您遵守 equals 和 hashCode 的约定,以使您的集合(使用密钥的任何标准集合)按预期工作。

      这里我只使用了 Eclipse 生成的生成方法,但也有许多动态实用程序(例如在 Guava 中)可以帮助您解决这个问题。

      【讨论】:

        【解决方案4】:

        还有适合这种情况的连接键的简单替代方法:

        public static String getKey(String name, int number) {
            return name + number;
        }
        

        如果名称不太长,则字符串连接的开销不会大于其他答案中建议的创建复合键对象的开销。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-13
          • 2019-01-06
          • 2012-02-14
          • 1970-01-01
          • 2015-02-20
          • 1970-01-01
          相关资源
          最近更新 更多