名前+数値にバインドされた値を保存したい。たとえば、(John、1)(RED)と(John、2)(BLUE)と(Elize、1)(GREEN)では、一意に組み合わされた2つのキーをどのように保存できますか?
4 に答える
複合キー (ここでは名前と番号) を表す新しい型を作成します。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);
}
}
Objects.equal
ここで明示的な nullity チェックを避けるために、便宜上 from Guava を使用しています。Guava を使用していない場合は、同等のものを使用するか、コードで nullity を処理する必要があります。または、null 名を防止して、コンストラクターでこれを検証することもできます。
組み合わせの一意性に確信があり、キー オブジェクトを簡単に文字列化できる場合は、文字列連結を使用します。キーを結合するために特殊文字を使用する場合があります (「John#1」と「John#2」など)。
よくわからない場合は、Guava's Tableを使用します。
通常、一度に複数のキーのインデックスを作成しようとすると、Map(FirstName, Map(LastName, Person)) のようなものになってしまい、見苦しく使いにくいものになります。Guava は、任意の「行」タイプと「列」タイプのこのユース ケースをサポートする新しいコレクション タイプ テーブルを提供します。
したがって、テーブルは
行キーと列キーと呼ばれるキーの順序付けられたペアを単一の値に関連付けるコレクション。
次のように特定の 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 など) もあります。
この場合に適した連結キーを使用した簡単な代替アプローチもあります。
public static String getKey(String name, int number) {
return name + number;
}
名前が長すぎない場合、文字列連結のオーバーヘッドは、他の回答で提案されている複合キー オブジェクトを作成する場合よりも大きくなりません。