2

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

4

4 回答 4

5

创建一个表示复合键的新类型(此处为名称和数字)。您需要覆盖hashCode()and 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);
    }
}

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

于 2012-09-28T06:53:27.240 回答
2

I'll use a String concatenation if I'm sure about the uniqueness of the combination and if the keys object are easy to stringify. I might use a special character to join the keys (like "John#1" and "John#2").

If I'm not sure about that I'll use Guava's Table:

Typically, when you are trying to index on more than one key at a time, you will wind up with something like Map(FirstName, Map(LastName, Person)), which is ugly and awkward to use. Guava provides a new collection type, Table, which supports this use case for any "row" type and "column" type

So a Table is

A collection that associates an ordered pair of keys, called a row key and a column key, with a single value.

于 2012-09-28T07:01:52.607 回答
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 中)可以帮助您解决这个问题。

于 2012-09-28T06:55:21.680 回答
0

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

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

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

于 2012-09-28T07:04:48.380 回答