Da es einige Unklarheiten darüber gibt, welchen Algorithmus Javas HashMap verwendet (in der Sun / Oracle / OpenJDK-Implementierung), hier die relevanten Quellcode-Schnipsel (aus OpenJDK, 1.6.0_20, unter Ubuntu):
/**
* Returns the entry associated with the specified key in the
* HashMap. Returns null if the HashMap contains no mapping
* for the key.
*/
final Entry<K,V> getEntry(Object key) {
int hash = (key == null) ? 0 : hash(key.hashCode());
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
}
return null;
}
Diese Methode (zitieren ist von Linien 355-371) aufgerufen wird , wenn ein Eintrag in der Tabelle nach oben, zum Beispiel aus get()
, containsKey()
und einige andere. Die for-Schleife durchläuft hier die verknüpfte Liste, die von den Eingabeobjekten gebildet wird.
Hier der Code für die Eingabeobjekte (Zeilen 691-705 + 759):
static class Entry<K,V> implements Map.Entry<K,V> {
final K key;
V value;
Entry<K,V> next;
final int hash;
/**
* Creates new entry.
*/
Entry(int h, K k, V v, Entry<K,V> n) {
value = v;
next = n;
key = k;
hash = h;
}
// (methods left away, they are straight-forward implementations of Map.Entry)
}
Gleich danach kommt die addEntry()
Methode:
/**
* Adds a new entry with the specified key, value and hash code to
* the specified bucket. It is the responsibility of this
* method to resize the table if appropriate.
*
* Subclass overrides this to alter the behavior of put method.
*/
void addEntry(int hash, K key, V value, int bucketIndex) {
Entry<K,V> e = table[bucketIndex];
table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
if (size++ >= threshold)
resize(2 * table.length);
}
Dadurch wird der neue Eintrag auf der Vorderseite des Buckets mit einem Link zum alten ersten Eintrag hinzugefügt (oder null, falls kein solcher vorhanden ist). In ähnlicher removeEntryForKey()
Weise geht die Methode die Liste durch und sorgt dafür, dass nur ein Eintrag gelöscht wird, wobei der Rest der Liste intakt bleibt.
Hier ist also eine verknüpfte Eintragsliste für jeden Bucket, und ich bezweifle sehr, dass sich dies von _20
zu geändert hat _22
, da es ab 1.2 so war.
(Dieser Code ist (c) 1997-2007 Sun Microsystems und unter GPL verfügbar. Verwenden Sie zum besseren Kopieren jedoch die Originaldatei, die in src.zip in jedem JDK von Sun / Oracle und auch in OpenJDK enthalten ist.)