2016-03-19 11 views
5

Ich analysiere den HashMap Quellcode in Java und bekomme eine Frage über die put Methode.Warum vergleicht HashMap.put Hashwerte und testet die Gleichheit?

Unten ist die put Methode in JDK1.6:

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; 
} 

ich verwirrt über die if (e.hash == hash && ((k = e.key) == key || key.equals(k)))

Warum die Bedingung so?

Da in Java Superklasse Object, gibt es eine contract von hashCode und equals:

Wenn zwei Objekte gleich sind dem Gleichheits nach (Object) -Methode, dann die Methode hashCode auf jeder der beiden Aufruf Objekte müssen das gleiche ganzzahlige Ergebnis erzeugen.

Also die key.equals(k) bedeutet key.hashCode() == k.hashCode().

Die hash() ist unten:

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); 
} 

so key.hashCode() == k.hashCode() impliziert e.hash == hash.

Also warum ist nicht die Bedingung wie if ((k = e.key) == key || key.equals(k))?

Antwort

6

Es ist nur ein Methodenaufruf zu vermeiden, wenn es kann: Wenn der Hash (die nicht hashCode() ist, ist es die eigene Hashing der Karte ist) aus dem Hash-Beitritt ist anders, es weiß es nicht equals zu nennen hat bei alle. Einfach ein bisschen optimieren.

6

Es ist nur eine Optimierung: zwei Ganzzahlen zu vergleichen ist schneller als equals() aufrufen.

Wenn sich die beiden Hashcodes unterscheiden, dann weiß die Karte basierend auf dem Vertrag von equals und hashCode, dass der vorhandene Schlüssel nicht dem angegebenen Schlüssel entspricht und schneller zum nächsten springen kann.

1

Der Wert der 'Hash'-Variable kann sich vom Hashcode unterscheiden. 'hash' Variable ist das Ergebnis der Methode 'hash (key.hashCode())'. Daher ist es erforderlich, die Hash-Werte und auch die Gleichheit der Schlüssel zu vergleichen.

Verwandte Themen