La question est (maintenant) à propos de stocker beaucoup de données, qui peuvent être représentés à l'aide de primitives de type int
, dans une Carte. Quelques réponses ici sont très trompeuses, à mon avis. Nous allons voir pourquoi.
J'ai modifié l'indice de référence du trésor pour les mesures d'exécution et la consommation de mémoire. J'ai aussi ajouté des PCJ à cette référence, qui est une autre des collections de la bibliothèque de types primitifs (j'ai utiliser beaucoup). Le "officiel" du trésor de référence ne permet pas de comparer IntIntMaps à Java de la Collection" Map<Integer, Integer>
, probablement stocker Integers
et stocker ints
n'est pas la même chose d'un point de vue technique. Mais un utilisateur peut ne pas se soucier de cette technique en détail, il veut stocker des données qui peuvent être représentés avec ints
efficacement.
D'abord la partie du code:
new Operation() {
private long usedMem() {
System.gc();
return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}
// trove
public void ours() {
long mem = usedMem();
TIntIntHashMap ours = new TIntIntHashMap(SET_SIZE);
for ( int i = dataset.size(); i-- > 0; ) {
ours.put(i, i);
}
mem = usedMem() - mem;
System.err.println("trove " + mem + " bytes");
ours.clear();
}
public void pcj() {
long mem = usedMem();
IntKeyIntMap map = new IntKeyIntOpenHashMap(SET_SIZE);
for ( int i = dataset.size(); i-- > 0; ) {
map.put(i, i);
}
mem = usedMem() - mem;
System.err.println("pcj " + mem + " bytes");
map.clear();
}
// java collections
public void theirs() {
long mem = usedMem();
Map<Integer, Integer> map = new HashMap<Integer, Integer>(SET_SIZE);
for ( int i = dataset.size(); i-- > 0; ) {
map.put(i, i);
}
mem = usedMem() - mem;
System.err.println("java " + mem + " bytes");
map.clear();
}
Je suppose que les données proviennent primitive ints
, ce qui semble sain d'esprit. Mais cela implique un temps d'exécution de la peine pour des java util, en raison de l'auto-boxing, ce qui n'est pas nécessaire pour le primitif collections de cadres.
Le moteur d'exécution de résultats (sans gc()
des appels, bien sûr) sur WinXP, jdk1.6.0_10:
100000 mettre opérations de 100000 contient des opérations
java collections 1938 ms 203 ms
trove 234 ms 125 ms
pcj 516 ms 94 ms
Même si cela peut déjà sembler drastique, ce n'est pas la raison de l'utilisation d'un tel cadre.
La raison en est les performances de la mémoire. Les résultats pour une Carte contenant 100000 int
entrées:
java collections oscille entre 6644536 et 7168840 octets
mine de 1853296 octets
pcj 1866112 octets
Java Collections besoins de plus de trois fois la mémoire par rapport à la collection primitive cadres. I. e. vous pouvez garder trois fois plus de données dans la mémoire, sans avoir recours à des e / s disque qui diminue les performances d'exécution par des grandeurs. Et c'est important. Lire highscalability pour savoir pourquoi.
Dans mon expérience forte consommation de la mémoire est le plus grand problème de performance avec Java, qui, bien sûr, les résultats dans le pire des performances d'exécution. Collection Primitive cadres peuvent vraiment aider ici.
Donc: Pas de java.util n'est pas la réponse. Et "ajouter des fonctionnalités" à la Java des collections n'est pas le point quand on parle d'efficacité. Aussi le moderne JDK collections ne sont pas "hors-même spécialisées de Trésors des collections".
Avertissement: La référence ici est loin d'être complète, il n'est ni parfait. Il est destiné à conduire à la maison le point, j'ai vécu dans de nombreux projets. Primitive collections sont utiles à tolérer de poisson API - si vous travaillez avec beaucoup de données.