HashSet<String[]> boog = new HashSet<String[]>();
boog.add(new String[]{"a", "b", "c"});
boog.add(new String[]{"a", "b", "c"});
boog.add(new String[]{"a", "b", "d"});
結果は
[a, b, c]
[a, b, d]
[a, b, c]
どこ [a,b,c]
が繰り返されているため、ハッシュ関数が期待どおりに機能していません。文字列配列のハッシュメソッドをオーバーライドするにはどうすればよいですか。それとも、一般的な配列ですか?私がやろうとしていることを達成するためのより良い方法はありますか?
できません。配列は、デフォルトのIDベースのObject.hashCode()実装を使用します。これをオーバーライドする方法はありません。 HashMap/HashSetで配列をキーとして使用しないでください。
代わりにリストのセットを使用してください。
「より良い方法」は、コレクションを使用することです。 String[]
の代わりにList
を使用してください:
Set<List<String>> boog = //...
boog.add(Arrays.asList("a", "b", "c"));
boog.add(Arrays.asList("a", "b", "c"));
boog.add(Arrays.asList("a", "b", "d"));
System.out.println(boog.size()); // 2
配列をキーとして使用する必要がある場合は、各キーの周囲に透明なラッパーを作成して、マップに配置できます。いくつかのライブラリはそれを手助けします。たとえば、 Trove を使用してSet<String[]>
を実行する方法は次のとおりです。
Set<String[]> boog = new TCustomHashSet<String[]>(new ArrayHashingStrategy());
boog.add(new String[]{"a", "b", "c"});
boog.add(new String[]{"a", "b", "c"});
boog.add(new String[]{"a", "b", "d"});
System.out.println(boog.size()); // 2
//...
public class ArrayHashingStrategy extends HashingStrategy<Object[]> {
public int computeHashCode(Object[] array) {
return Arrays.hashCode(array);
}
public boolean equals(Object[] arr1, Object[] arr2) {
return Arrays.equals(arr1, arr2);
}
}
配列のhashCode()
はデフォルトの実装を使用しますが、これは要素を考慮に入れていないため、変更することはできません。
代わりに、List
を使用できます。hashCode()
は、その要素のハッシュコードに基づいて計算されます。 ArrayList
(ほとんどの実装として)は、このような関数を使用します。
別の方法(ただし、配列の使用を強制されない限り、あまり好ましくない)では、key.hashCode()
を呼び出す代わりに、「特別な」HashSet
を使用できます。Arrays.hashCode(array)
を呼び出します。これを実装するには、HashMap
を拡張してからCollections.newSetFromMap(map)
を使用します
実際には、すべての異なる配列に対して異なる値を返すデフォルトのhashCode
メソッドを使用しています!
これを解決する最良の方法は、Collection
(List
やSet
など)を使用するか、次のような独自のラッパークラスを定義することです。
public class StringArray {
public String[] stringArray;
[...] // constructors and methods
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
for(String string : stringArray){
result = prime * result + ((string == null) ? 0 : string.hashCode());
}
}
}
このクラスは実際にはhashCode
のメソッドとほとんど同じList
メソッドを使用します。
あなたは今扱う:
HashSet<StringArray> boog = new HashSet<StringArray>();
実際にできます。 TreeSet
は、提供されたComparator
とともに使用できます。あなたの場合、それは次のようなものになります:
Set<String[]> boog = new TreeSet<>((o1, o2) -> {
for (int i = 0; i < o1.length; i++){
int cmp = o1[i].compareTo(o2[i]);
if (cmp != 0) {
return cmp;
}
}
return o1.length - o2.length;
});
フードの下では、アルファベット順にソートされたツリーのように見えます。