Considérez le code HashMap.clear()
suivant:
/**
* Removes all of the mappings from this map.
* The map will be empty after this call returns.
*/
public void clear() {
modCount++;
Entry[] tab = table;
for (int i = 0; i < tab.length; i++)
tab[i] = null;
size = 0;
}
Il semble que le tableau interne (table
) des objets Entry
ne soit jamais réduit. Ainsi, lorsque j'ajoute 10000 éléments à une carte, et après cet appel map.clear()
, il conservera 10000 valeurs nulles dans son tableau interne. Donc, ma question est, comment la JVM gère-t-elle ce tableau de rien, et donc, la mémoire HashMap
est-elle efficace?
L'idée est que clear()
n'est appelée que lorsque vous souhaitez réutiliser HashMap
. La réutilisation d'un objet ne doit être effectuée que pour la même raison que celle utilisée auparavant, il y a donc de fortes chances que vous ayez à peu près le même nombre d'entrées. Pour éviter un rétrécissement et un redimensionnement inutiles du Map
, la capacité est maintenue la même lorsque clear()
est appelée.
Si tout ce que vous voulez faire est de supprimer les données dans le Map
, vous n'avez pas besoin (et en fait ne devriez pas) appeler clear()
dessus, mais simplement effacer toutes les références au Map
lui-même, auquel cas il sera éventuellement récupéré.
En regardant le code source , il semble que HashMap
ne rétrécit jamais. La méthode resize
est appelée pour doubler la taille chaque fois que cela est nécessaire, mais n'a rien d'ala ArrayList.trimToSize()
.
Si vous utilisez un HashMap
de telle manière qu'il augmente et diminue de façon spectaculaire souvent, vous pouvez simplement créer un nouveau HashMap
au lieu d'appeler clear()
.
Vous avez raison, mais étant donné que l'augmentation du tableau est une opération beaucoup plus coûteuse, il n'est pas déraisonnable pour le HashMap de penser "une fois que l'utilisateur a augmenté le tableau, il est probable qu'il aura besoin du tableau de cette taille plus tard" et quitte simplement le tableau au lieu de le diminuer et de risquer d'avoir à le développer à nouveau plus tard. C'est une heuristique, je suppose - vous pouvez également préconiser l'inverse.
Une autre chose à considérer est que chaque élément dans table
est simplement une référence. La définition de ces entrées sur null supprimera les références des éléments de votre Map
, qui seront ensuite libres pour la récupération de place. Ce n'est donc pas comme si vous ne libériez aucune mémoire.
Cependant, si vous avez besoin de libérer même la mémoire utilisée par le Map
lui-même, vous devez le libérer conformément à la suggestion de Joachim Sauer.