如何在HashMap中存储2个组合的唯一键?

时间:2012-09-28 06:51:49

标签: java hashmap key-value unique-key

我想存储绑定到名称+数字的值。 喜欢,(John,1)(RED)和(John,2)(BLUE)和(Elize,1)(GREEN) 那么如何存储两个结合独特的键呢?

4 个答案:

答案 0 :(得分:5)

创建一个表示复合键的新类型(此处为名称和数字)。您需要覆盖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,则必须在代码中使用等效或处理无效。或者,您可能希望阻止空名称,在构造函数中验证它。

答案 1 :(得分:2)

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

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

  

通常,当您尝试在a处索引多个键时   时间,你会结束像地图(FirstName,   Map(LastName,Person)),这是丑陋和难以使用的。番石榴   提供了一个新的集合类型Table,它支持这个用例   对于任何“行”类型和“列”类型

所以表是

  

关联一组有序键的集合,称为行键   和一个列密钥,具有单个值。

答案 2 :(得分:1)

定义您的特定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中)帮助你完成这个主题。

答案 3 :(得分:0)

还有一种简单的替代方法,使用适用于这种情况的连接键:

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

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