HashMapでキーの存在を確認することは常に必要ですか?
私は1000エントリを言うとHashMapを持っていると私は効率を向上させることを検討しています。 HashMapが非常に頻繁にアクセスされている場合は、アクセスごとにキーの存在を確認すると、大きなオーバーヘッドが発生します。キーが存在しないために例外が発生した場合は、例外をキャッチできます。 (これがめったに起こらないことを私が知っているとき)。これにより、HashMapへのアクセスが半分に減ります。
これは良いプログラミング方法ではないかもしれませんが、アクセス数を減らすのに役立ちます。それとも私はここで何かが足りないのですか?
[ Update ] HashMapにnull値がありません。
Null値を格納したことはありますか?そうでなければ、あなただけのことができます:
Foo value = map.get(key);
if (value != null) {
...
} else {
// No such key
}
そうでなければ、 を返すことができます あなたが返されたnull値を取得する場合は単に存在を確認します。
Foo value = map.get(key);
if (value != null) {
...
} else {
// Key might be present...
if (map.containsKey(key)) {
// Okay, there's a key but the value is null
} else {
// Definitely no such key
}
}
キーが存在することを確認しても何も得られません。これはHashMap
のコードです。
@Override
public boolean containsKey(Object key) {
Entry<K, V> m = getEntry(key);
return m != null;
}
@Override
public V get(Object key) {
Entry<K, V> m = getEntry(key);
if (m != null) {
return m.value;
}
return null;
}
get()
の戻り値がnull
と異なるかどうかを確認してください。
これがHashMapのソースコードです。
リソース:
もっと良い方法はHashMapのcontainsKeyメソッドを使うことです。明日のように、具体化するとマップにnullが追加されるので、そこにあるキーとnullの値を持つキーを区別する必要があります。
あなたはあなたのようなコードを持っているという意味ですか?
if(map.containsKey(key)) doSomethingWith(map.get(key))
あらゆる所に ?それならmap.get(key)
がnullを返したかどうかをチェックしてください。ちなみに、HashMapは欠けているキーに対して例外を投げません。代わりにnullを返します。 containsKey
が必要とされる唯一のケースは、null値と欠損値を区別するためにnull値を格納するときですが、これは通常悪い習慣と考えられています。
わかりやすくするためにcontainsKey()
を使用してください。それは速く、コードをきれいにそして読みやすく保ちます。 HashMap
sのポイントは、キー検索が高速であることです。hashCode()
とequals()
が正しく実装されていることを確認してください。
if(map.get(key) != null || (map.get(key) == null && map.containsKey(key)))
Jon Skeetの答え は、2つのシナリオ(null
値ではなくnull
値でマップする)を効率的に解決します。
エントリー数と効率の問題について、何か追加したいと思います。
私は1.000エントリを言うとHashMapを持っていると私は効率を向上させることを検討しています。 HashMapが非常に頻繁にアクセスされている場合は、アクセスごとにキーの存在を確認すると、大きなオーバーヘッドが発生します。
1.000のエントリを持つマップは大きなマップではありません。
5.000または10.000のエントリを含む地図。Map
は、そのような次元で素早く検索するように設計されています。
今、マップキーのhashCode()
が良い分布を提供すると仮定します。
あなたがキータイプとしてInteger
を使うことができるならば、それをしてください。
衝突は一意のint
値に対しては不可能であるため、そのhashCode()
メソッドは非常に効率的です。
public final class Integer extends Number implements Comparable<Integer> {
...
@Override
public int hashCode() {
return Integer.hashCode(value);
}
public static int hashCode(int value) {
return value;
}
...
}
キーのために、例えばString
でよく使われる別の組み込み型をMap
として使わなければならない場合、衝突があるかもしれませんが、Map
の中には1000から数千のオブジェクトがありますString.hashCode()
メソッドは良いディストリビューションを提供します。
カスタムタイプを使用する場合は、hashCode()
とequals()
を正しくオーバーライドして、全体としてhashCode()
が公平に配布されるようにします。Java Effective
の項目9を参照している場合があります。
これが post です。
私は通常イディオムを使います
Object value = map.get(key);
if (value == null) {
value = createValue(key);
map.put(key, value);
}
これは、キーが見つからない場合にのみマップを2回押すということです。
HashMap
クラスで computeIfAbsent()
メソッドを使用することもできます。
次の例では、map
はキー(銀行口座の名前)に適用されるトランザクションのリスト(整数)を格納します。 100
と200
の2つのトランザクションをchecking_account
に追加するには、次のように書くことができます。
HashMap<String, ArrayList<Integer>> map = new HashMap<>();
map.computeIfAbsent("checking_account", key -> new ArrayList<>())
.add(100)
.add(200);
これにより、キーchecking_account
が存在するかどうかを確認する必要がなくなります。
computeIfAbsent()
によって返されます。本当にエレガント! ????