2016-03-19 4 views
5

JavaでソースコードHashMapを分析し、putメソッドについて質問があります。なぜHashMap.putはハッシュとテストの平等を比較しますか?

public V put(K key, V value) { 
    if (key == null) 
     return putForNullKey(value); 
    int hash = hash(key.hashCode()); 
    int i = indexFor(hash, table.length); 
    for (Entry<K,V> e = table[i]; e != null; e = e.next) { 
     Object k; 
     if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { 
      V oldValue = e.value; 
      e.value = value; 
      e.recordAccess(this); 
      return oldValue; 
     } 
    } 

    modCount++; 
    addEntry(hash, key, value, i); 
    return null; 
} 

は、私はこのような状態であるのはなぜif (e.hash == hash && ((k = e.key) == key || key.equals(k)))

についての混乱:以下

はJDK1.6で put方法ですか?

のJavaスーパークラスObjectに、hashCodeequalscontractがあるので:

2つのオブジェクトが2つのそれぞれにhashCodeメソッドを呼び出して、等しい(オブジェクト)の方法に従って等しい場合オブジェクトは同じ整数結果を生成する必要があります。

したがって、key.equals(k)key.hashCode() == k.hashCode()を意味します。

hash()は以下である:

static int hash(int h) { 
    // This function ensures that hashCodes that differ only by 
    // constant multiples at each bit position have a bounded 
    // number of collisions (approximately 8 at default load factor). 
    h ^= (h >>> 20)^(h >>> 12); 
    return h^(h >>> 7)^(h >>> 4); 
} 

従ってkey.hashCode() == k.hashCode()e.hash == hashことを意味します。

なぜ、条件がif ((k = e.key) == key || key.equals(k))のようになっていないのですか?

答えて

6

それができたときにそれはちょうどメソッド呼び出しを避けています:ハッシュ、エントリのハッシュと異なっている(ないhashCode()で、それはマップの独自のハッシュだ)、それを知っている場合、それはでequalsを呼び出す必要はありません。すべて。ちょっとだけ最適化する。

6

これはちょうど最適化です:2つの整数の比較は、equals()を呼び出すよりも高速です。

equalshashCodeの契約に基づいて、2つのハッシュコードが異なる場合、マップは既存のキーが指定されたキーと等しくないことを認識し、次のキーに速く進むことができます。

1

'hash'変数の値は、キーのハッシュコードと異なる場合があります。 'hash'変数は 'hash(key.hashCode())'メソッドを呼び出した結果です。したがって、ハッシュ値とキーの等価性を比較する必要があります。

関連する問題