Je parcourais le code source de HashMap de Java quand j'ai vu ce qui suit
//The default initial capacity - MUST be a power of two.
static final int DEFAULT_INITIAL_CAPACITY = 16;
Ma question est pourquoi cette exigence existe-t-elle en premier lieu? Je vois également que le constructeur qui permet de créer un HashMap avec une capacité personnalisée le convertit en une puissance de deux:
int capacity = 1;
while (capacity < initialCapacity)
capacity <<= 1;
Pourquoi la capacité doit-elle toujours être une puissance de deux?
De plus, lorsque le ré-hachage automatique est effectué, que se passe-t-il exactement? La fonction de hachage est-elle également modifiée?
La carte doit déterminer quel index de table interne utiliser pour une clé donnée, en mappant toute valeur int
(qui pourrait être négative) à une valeur dans la plage [0, table.length)
. Quand table.length
est une puissance de deux, ce qui peut être fait vraiment à moindre coût - et est, dans indexFor
:
static int indexFor(int h, int length) {
return h & (length-1);
}
Avec une longueur de table différente, vous devez calculer un reste et vous assurer qu'il n'est pas négatif. Il s'agit certainement d'une micro-optimisation, mais probablement valide :)
De plus, lorsque le ré-hachage automatique est effectué, que se passe-t-il exactement? La fonction de hachage est-elle également modifiée?
Je ne comprends pas très bien ce que vous voulez dire. Les mêmes codes de hachage sont utilisés (car ils sont simplement calculés en appelant hashCode
sur chaque clé) mais ils seront distribués différemment dans la table en raison de la longueur de la table qui change. Par exemple, lorsque la longueur de la table est 16, les codes de hachage de 5 et 21 finissent tous les deux par être stockés dans l'entrée de table 5. Lorsque la longueur de la table augmente à 32, ils seront dans des entrées différentes.
La situation idéale consiste en fait à utiliser des nombres premiers pour le tableau de support d'un HashMap
. De cette façon, vos clés seront distribuées plus naturellement à travers le tableau. Cependant, cela fonctionne avec la division mod et cette opération est devenue de plus en plus lente avec chaque version de Java. Dans un sens, la puissance de 2 est la pire taille de table que vous puissiez imaginer, car avec des implémentations de code de hachage médiocres, elles sont plus susceptibles de produire des collosions clés dans le tableau.
Pour cela, vous trouverez une autre méthode très importante dans l'implémentation de HashMap
de Java, qui est la hash(int)
, qui compense les codes de hachage pauvres.