1

このクラスの関数を作成しましたが、hashcodeなんらかの理由で、キーが実際にHashMap. (座標は文字列)

@Override
public int hashCode() {
    return coordinates.hashCode();
}

.equalsまた、2 組の座標が互いに等しいかどうかをテストするクラスのメソッドも作成しました。ただし、ハッシュコード メソッドが正しく機能していることを確認するために、.equalsメソッドを次のように切り替えました。

public boolean equals(Object arg) {
    Block a = (Block) arg;
    return hashCode() == a.hashCode();
}

そして、それらはすべて、次のような呼び出しで他の場所でhashmap.containskey()呼び出されています。

return (hashblocks.containsKey(newz));

何らかの理由で、これは true ~ 50% の場合にのみ返されます (まったく同じケースを再入力することさえありますが、機能する場合と機能しない場合があります)。HashMaps とs で適切に動作するようにするSetには、特にこの実装に問題があるのはなぜだろうと思っています。(基本的に、バグは何である可能性があります)

3 1 3 1
true
4 2 4 2
false
 0 0 1 0
 0 3 1 3
 2 0 3 0
 2 3 3 3
0 1 1 2
2 1 2 2
4 0 4 0
4 2 4 2
3 1 3 1
3 2 3 2

3 1 3 1
true
4 2 4 2
true
3 2 3 2
true
 0 0 1 0
 0 3 1 3
 2 0 3 0
 3 3 4 3
0 1 1 2
2 1 2 2
4 0 4 0
4 2 4 2
3 1 3 1
3 2 3 2

クエリの後にはその結果が続き、数値の長いセットはすべてのキーとそれに続く改行文字を表します

4

2 に答える 2

2

ハッシュコード メソッドが正しく機能していることを確認するために、.equals メソッドを次のように切り替えました。

return hashCode()==a.hashCode();

これは、「完全なハッシュ」の場合、つまり、ハッシュ コードの等価性が実際の値の等価性を意味する場合にのみ機能します。Javaのハッシュ コードはString完全ではありません (実際、理論上でも可能なすべての文字列に対して完全であるとは言えません)。

等値チェックをハッシュコードと一致させる必要があります-あなたの場合、それは次の等値をチェックすることになりますcoordinates:

public boolean equals(Object arg) {
    Block a = (Block) arg;
    return coordinates.equals(a.coordinates);
}
于 2014-08-16T12:32:36.550 に答える
2

座標は可変に見えるhashCode()ため、ハッシュベースのコンテナーで問題が発生するため、として使用しないでください。

Map<Object,Object> map = new HashMap<>();
key.setCoordinates("1");
map.put(key, value1); 
key.setCoordinates("2");
map.put(key, value2); 

キーは同じままですが、どちらが可変であるかhashCodeに基づいています。coordinates最初のケースではcoordinates == "1"、その値は 1 である可能性があります。ハッシュ マップ/セットは特定の容量 (16 など) の内部配列を使用するため、次の位置に value1 を格納します。

map.values[(key.hashCode() % map.values.length)] = value1;
map.values[(1 % 16)] = value1;
map.values[1] = value1;

実際、配列はリストの配列です (例: 2 つのキーが同じハッシュ コードを持っている可能性があり、そこで equals メソッドが使用されます) が、Java での HashMap/Set の完全な実装については触れたくありません。

mutateの場合、 2 回目のhashCode呼び出しputは機能しません。つまり、それ"2".hashCode()が 2 で、それkey.hashCode()も 2 を返します。

map.values[(key.hashCode() % map.values.length)] = value2;
map.values[(2 % 16)] = value2;
map.values[2] = value2;

しかし、同じキーに対して、既に値が関連付けられていますが、value2 に置き換えられていません。ランダムな順序でSystem.out.println(map);印刷されると想定することもできます。[key: value1, key: value2]

そのため、マップを使用するときにキーが決して変更されないことが確実でない限り、hashCodeメソッドは変更フィールドの使用を避ける必要があります。

おそらく 0 を返すか、デフォルトを使用する必要がありますhashCode()/equals()

equals でも同じ問題が発生する可能性があります。

于 2014-08-16T13:09:05.437 に答える