Como existe cierta confusión sobre qué algoritmo está usando Java HashMap (en la implementación de Sun / Oracle / OpenJDK), aquí los fragmentos de código fuente relevantes (de OpenJDK, 1.6.0_20, en 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;
}
Este método (la cita es de las líneas 355 a 371) se llama al buscar una entrada en la tabla, por ejemplo get()
, de , containsKey()
y algunas otras. El bucle for aquí pasa por la lista vinculada formada por los objetos de entrada.
Aquí el código para los objetos de entrada (líneas 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)
}
Inmediatamente después de esto viene el addEntry()
método:
/**
* 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);
}
Esto agrega la nueva entrada en la parte delantera del cubo, con un enlace al antiguo primero entrada anterior (o nula, si no existe). De manera similar, el removeEntryForKey()
método recorre la lista y se encarga de eliminar solo una entrada, dejando intacto el resto de la lista.
Entonces, aquí hay una lista de entrada vinculada para cada segmento, y dudo mucho que esto haya cambiado de _20
a_22
, ya que fue así desde 1.2 en adelante.
(Este código es (c) 1997-2007 Sun Microsystems, y está disponible bajo GPL, pero para copiar mejor use el archivo original, contenido en src.zip en cada JDK de Sun / Oracle, y también en OpenJDK.)