ハッシュマップを作成し、キーと値のエントリを入力しました。値はオブジェクトです。マップには、少なくとも 10,000 のエントリが含まれています。後で特定のキーを使用して値を取得したい場合、マップはこのエントリを見つけられないようです。これは奇妙すぎる。毎回別のエントリで失敗しています。これをトラブルシューティングするにはどうすればよいですか? サーバーとしてweblogicを使用しています。環境値で遊ぶ必要がありますか?
4 に答える
エントリが「失われる」原因となる可能性があるものを次に示します。
キー オブジェクトに equals / hashcode メソッドが正しく実装されていません。これら 2 つのメソッドは、ハッシュ テーブルが適切に機能するための「コントラクト」に準拠する必要があります。最も重要なプロパティは次のとおりです。
key1.equals(key2) IMPLIES key1.hashcode() == key2.hashcode
キーがマップで使用されている間に変更される可変キー オブジェクト。特に、キーの変更によってキーのハッシュコードが変更された場合、キーのハッシュコードは失われます。(この場合、マップ全体を反復処理すると、エントリが表示されます。しかし、ハッシュ チェーンが間違っているため、has lookup を使用するマップ操作ではエントリが見つかりません。)
最も安全な方法は、不変のキー クラスを使用することです。
適切な同期を行わずにマルチスレッド アプリケーションでマップを使用する。これにより、マップ データ構造が破損し、エントリが失われる可能性があります。
あなたが気付いていないアプリケーションの他の部分は、エントリの削除です。
オーバーライドする必要がequals
あり、hashcode
間違っていると述べている/述べている回答。Object
これらのメソッドの実装がまさに必要なものである状況があります。あなたがしなければならないことは、次のことを確認することです:
- ユースケースで必要とされる適切な形式のキーの等価性を使用している、および
- あなた
equals
とhashcode
「契約」に従います。
これをトラブルシューティングするにはどうすればよいですか?
上記の問題を確認するためにコードインスペクションをお勧めします。
デバッグは別の方法です。たとえば、間違ったハッシュ チェーンで不足しているエントリを見つけることができるかどうかを調べることができます。ただし、そのアプローチは少し「ヒットアンドミス」になる可能性があると思います。
サーバーとしてweblogicを使用しています。
関係ありません...J2SEではなくWeblogicによって実装されたMap実装クラスを使用している場合を除きます。(オブジェクトのクラス名を見てください。)
環境値で遊ぶ必要がありますか?
いいえ、役に立ちません
1 つの考えられるシナリオは次のとおりです。
キーがクラスのインスタンスであり、そのクラスが equals/hashcode メソッドをオーバーライドしていない場合、get メソッドは false を返すことがあります。
キーが変更可能な場合、ハッシュ値を変更する方法でキーを変更すると、ルックアップが失敗します。
たとえば、次の可変クラスがあるとします。
public class MyKey {
private int value;
public void setValue(int value) {
this.value = value;
}
public int hashCode() {
return value;
}
public boolean equals(Object obj) {
//...
}
}
次に、これが可能です:
MyKey key = new MyKey();
key.setValue(1);
Map<MyKey, String> map = new HashMap<MyKey, String>();
map.put(key, "Hello");
System.out.println("map contains: " + map.get(key)); // "map contains: Hello"
key.setValue(2);
System.out.println("map contains: " + map.get(key)); // "map contains: "
ナンバリの答えを拡張するには:
equals と hashCode をキーとしてオーバーライドしないクラスを使用する場合、等価性はオブジェクトの等価性に基づきます (例: 同じオブジェクト アドレス、同じコンテンツではありません)。== で文字列を比較できないのと同じ理由です。
class Key {
public String k;
public Key(String k) { this.k = k; }
/*
//with this it would work.
public boolean equals(Object o) {
if (o instanceof Key) return ((Key)o).k.equals(k);
return false;
}
public int hashCode() {
return k.hashCode();
}
*/
}
map.put(new Key("a"),"test");
map.get(new Key("a")); // does NOT return "test" because key is another instance.