私は知っておく必要があります:javaのHashMap.containsKey()の時間の複雑さは何ですか?
この実装は、ハッシュ関数がバケット間で要素を適切に分散すると仮定して、基本操作(getおよびput)に一定時間のパフォーマンスを提供します。
containsKey()
は取得した値を捨てるget()
にすぎないため、O(1)(ハッシュ関数が適切に機能すると仮定))です。
通常O(1)ですが、不適切なhashCode関数を使用している場合は、1つのバケットに複数の要素を追加して、最悪の場合O(n)になるようにする必要があります。
一般的にはO(1)
ですが、最悪の場合はO(n)
です
public boolean containsKey(Object key) {
352 return getEntry(key) != null;
353 }
354
355 /**
356 * Returns the entry associated with the specified key in the
357 * HashMap. Returns null if the HashMap contains no mapping
358 * for the key.
359 */
360 final Entry<K,V> getEntry(Object key) {
361 int hash = (key == null) ? 0 : hash(key.hashCode());
362 for (Entry<K,V> e = table[indexFor(hash, table.length)];
363 e != null;
364 e = e.next) {
365 Object k;
366 if (e.hash == hash &&
367 ((k = e.key) == key || (key != null && key.equals(k))))
368 return e;
369 }
370 return null;
371 }
containsKey
の時間の複雑さはJDK-1.8で変更されました。他の人が述べたように、理想的なケースではO(1)
です。ただし、keys
がComparable
である衝突の場合、衝突要素を格納するビンは、TREEIFY_THRESHOLD
と呼ばれるしきい値を超えた後、線形ではなくなります。
/**
* The bin count threshold for using a tree rather than list for a
* bin. Bins are converted to trees when adding an element to a
* bin with at least this many nodes. The value must be greater
* than 2 and should be at least 8 to mesh with assumptions in
* tree removal about conversion back to plain bins upon
* shrinkage.
*/
static final int TREEIFY_THRESHOLD = 8;
言い換えると、TreeNodes
は(TreeMap
にあるものと同様に)ビンを保存するために使用され(つまり、赤黒木構造)、O(lgn)
衝突の場合の複雑さ。
同じことがget(key)
にも当てはまります。両方のメソッドが内部でgetNode
を呼び出す場合
注:nここはbin
ではなくHashMap
のサイズです