1. Explication
Concernant la méthode Map traversal en Java, de nombreux articles recommandent l’utilisation de EntrySet, considéré comme bien plus efficace que keySet. La raison est la suivante : la méthode EntrySet obtient l'ensemble de toutes les clés et valeurs à la fois ; tandis que la méthode keySet n'obtient que l'ensemble des clés. Pour chaque clé, la valeur doit être recherchée une fois de plus dans la carte, réduisant ainsi le nombre de clés. efficacité globale. Alors, quelle est la situation réelle ?
Afin de comprendre le véritable écart dans les performances de traversée, y compris les différences dans différents scénarios tels que clé de traversée + valeur, clé de traversée, valeur de traversée, etc., j'ai essayé d'effectuer quelques tests comparatifs.
2. Tests comparatifs
Au début, seul un simple test a été effectué, mais les résultats ont montré que les performances de keySet étaient meilleures, ce qui m'a intrigué. Ne disent-ils pas tous qu'entrySet est évidemment meilleur que keySet ? Afin de vérifier davantage, différentes données de test ont été utilisées pour des tests comparatifs plus détaillés.
2.1 Données d'essai
2.1.1 Données de test HashMap
HashMap-1, la taille est de 1 million, la clé et la valeur sont toutes deux des chaînes, la valeur de la clé est 1, 2, 3...1 000 000 :
Copiez le code comme suit :
Map<String, String> map = new HashMap<String, String>();
Clé de chaîne, valeur ;
pour (i = 1; i <= num; i++) {
clé = "" + je;
valeur = "valeur" ;
map.put(clé, valeur);
}
HashMap-2, la taille est de 1 million, la clé et la valeur sont toutes deux des chaînes, la valeur de la clé est 50, 100, 150, 200,..., 50000000 :
Copiez le code comme suit :
Map<String, String> map = new HashMap<String, String>();
Clé de chaîne, valeur ;
pour (i = 1; i <= num; i++) {
clé = "" + (i * 50);
valeur = "valeur" ;
map.put(clé, valeur);
}
2.1.2 Données de test TreeMap
TreeMap-1, la taille est de 1 million, la clé et la valeur sont toutes deux des chaînes, la valeur de la clé est 1, 2, 3...1 000 000 :
Copiez le code comme suit :
Map<String, String> map = new TreeMap<String, String>();
Clé de chaîne, valeur ;
pour (i = 1; i <= num; i++) {
clé = "" + je;
valeur = "valeur" ;
map.put(clé, valeur);
}
TreeMap-2, la taille est de 1 million, la clé et la valeur sont toutes deux String, les valeurs clés sont 50, 100, 150, 200,..., 50000000, plus discrètes :
Copiez le code comme suit :
Map<String, String> map = new TreeMap<String, String>();
Clé de chaîne, valeur ;
pour (i = 1; i <= num; i++) {
clé = "" + (i * 50);
valeur = "valeur" ;
map.put(clé, valeur);
}
2.2 Scénario de test
Utilisez diverses méthodes d'écriture de keySet, EntrySet et Values pour tester trois scénarios : traversée de clé+valeur, traversée de clé et traversée de valeur.
2.2.1 Clé de parcours+valeur
keySet traverse clé+valeur (méthode d'écriture 1) :
Copiez le code comme suit :
Iterator<String> iter = map.keySet().iterator();
while (iter.hasNext()) {
clé = iter.next();
valeur = map.get(clé);
}
keySet traverse clé+valeur (méthode d'écriture 2) :
Copiez le code comme suit :
pour (clé de chaîne : map.keySet()) {
valeur = map.get(clé);
}
EntrySet traverse clé+valeur (méthode d’écriture 1) :
Copiez le code comme suit :
Iterator<Entry<String, String>> iter = map.entrySet().iterator();
Entrée <String, String> ;
while (iter.hasNext()) {
entrée = iter.next();
clé = entrée.getKey();
valeur = entrée.getValue();
}
EntrySet traverse clé+valeur (méthode d’écriture 2) :
Copiez le code comme suit :
pour (entrée Entry<String, String> : map.entrySet()) {
clé = entrée.getKey();
valeur = entrée.getValue();
}
2.2.2 Clé de déplacement
keySet traverse la clé (méthode d'écriture 1) :
Copiez le code comme suit :
Iterator<String> iter = map.keySet().iterator();
while (iter.hasNext()) {
clé = iter.next();
}
keySet traverse la clé (méthode d'écriture 2) :
Copiez le code comme suit :
pour (clé de chaîne : map.keySet()) {
}
EntrySet traverse la clé (méthode d'écriture 1) :
Copiez le code comme suit :
Iterator<Entry<String, String>> iter = map.entrySet().iterator();
while (iter.hasNext()) {
key = iter.next().getKey();
}
EntrySet traverse la clé (méthode d'écriture 2) :
Copiez le code comme suit :
pour (entrée Entry<String, String> : map.entrySet()) {
clé = entrée.getKey();
}
2.2.3 Valeur de déplacement
keySet traverse la valeur (méthode d'écriture 1) :
Copiez le code comme suit :
Iterator<String> iter = map.keySet().iterator();
while (iter.hasNext()) {
valeur = map.get(iter.next());
}
keySet traverse la valeur (méthode d'écriture 2) :
Copiez le code comme suit :
pour (clé de chaîne : map.keySet()) {
valeur = map.get(clé);
}
EntrySet traverse la valeur (méthode d'écriture 1) :
Copiez le code comme suit :
Iterator<Entry<String, String>> iter = map.entrySet().iterator();
while (iter.hasNext()) {
valeur = iter.next().getValue();
}
EntrySet traverse la valeur (méthode d'écriture 2) :
Copiez le code comme suit :
pour (entrée Entry<String, String> : map.entrySet()) {
valeur = entrée.getValue();
}
valeurs traverse la valeur (méthode d'écriture 1) :
Copiez le code comme suit :
Iterator<String> iter = map.values().iterator();
while (iter.hasNext()) {
valeur = iter.next();
}
valeurs traverse la valeur (méthode d'écriture 2) :
Copiez le code comme suit :
pour (Valeur de chaîne : map.values()) {
}
2.3 Résultats des tests
2.3.1 Résultats des tests HashMap
Unité : milliseconde | HashMap-1 | HashMap-2 |
| keySet traverse clé+valeur (méthode d'écriture 1) | 39 | 93 |
| keySet traverse clé+valeur (méthode d'écriture 2) | 38 | 87 |
| EntrySet traverse clé + valeur (méthode d'écriture 1) | 43 | 86 |
| EntrySet traverse clé + valeur (méthode d'écriture 2) | 43 | 85 |
Unité : milliseconde | HashMap-1 | HashMap-2 |
| keySet traverse la clé (méthode d'écriture 1) | 27 | 65 |
| keySet traverse la clé (méthode d'écriture 2) | 26 | 64 |
| EntrySet traverse la clé (méthode d'écriture 1) | 35 | 75 |
| EntrySet traverse la clé (méthode d'écriture 2) | 34 | 74 |
Unité : milliseconde | HashMap-1 | HashMap-2 |
| keySet traverse la valeur (méthode d'écriture 1) | 38 | 87 |
| keySet traverse la valeur (méthode d'écriture 2) | 37 | 87 |
| EntrySet traverse la valeur (méthode d'écriture 1) | 34 | 61 |
| EntrySet traverse la valeur (méthode d'écriture 2) | 32 | 62 |
| valeurs valeur transversale (méthode d'écriture 1) | 26 | 48 |
| valeurs valeur transversale (méthode d'écriture 2) | 26 | 48 |
2.3.2 Résultats des tests TreeMap
Unité : milliseconde | ArbreMap-1 | ArbreMap-2 |
| keySet traverse clé+valeur (méthode d'écriture 1) | 430 | 451 |
| keySet traverse clé+valeur (méthode d'écriture 2) | 429 | 450 |
| EntrySet traverse clé + valeur (méthode d'écriture 1) | 77 | 84 |
| EntrySet traverse clé + valeur (méthode d'écriture 2) | 70 | 68 |
Unité : milliseconde | ArbreMap-1 | ArbreMap-2 |
| keySet traverse la clé (méthode d'écriture 1) | 50 | 49 |
| keySet traverse la clé (méthode d'écriture 2) | 49 | 48 |
| EntrySet traverse la clé (méthode d'écriture 1) | 66 | 64 |
| EntrySet traverse la clé (méthode d'écriture 2) | 65 | 63 |
Unité : milliseconde | ArbreMap-1 | ArbreMap-2 |
| keySet traverse la valeur (méthode d'écriture 1) | 432 | 448 |
| keySet traverse la valeur (méthode d'écriture 2) | 430 | 448 |
| EntrySet traverse la valeur (méthode d'écriture 1) | 62 | 61 |
| EntrySet traverse la valeur (méthode d'écriture 2) | 62 | 61 |
| valeurs valeur transversale (méthode d'écriture 1) | 46 | 46 |
| valeurs valeur transversale (méthode d'écriture 2) | 45 | 46 |
3. Conclusion
3.1 Si vous utilisez HashMap
1. Lors du parcours simultané de la clé et de la valeur, la différence de performances entre les méthodes keySet et EntrySet dépend des conditions spécifiques de la clé, telles que la complexité (objets complexes), la discrétion, le taux de conflit, etc. En d’autres termes, cela dépend du coût de recherche de valeur dans HashMap. L'opération d'entrySet pour récupérer toutes les clés et valeurs à la fois a une surcharge de performances. Lorsque cette perte est inférieure à la surcharge de HashMap recherchant une valeur, l'avantage de performances d'entrySet sera reflété. Par exemple, dans le test de comparaison ci-dessus, lorsque la clé est la chaîne numérique la plus simple, keySet peut être plus efficace, prenant 10 % de temps en moins que EntrySet. De manière générale, il est recommandé d'utiliser EntrySet. Parce que lorsque la clé est très simple, ses performances peuvent être légèrement inférieures à celles de keySet, mais elles sont contrôlables à mesure que la clé devient plus compliquée, les avantages d'entrySet seront clairement reflétés ; Bien sûr, nous pouvons choisir en fonction de la situation réelle
2. Lorsque vous parcourez uniquement des clés, la méthode keySet est plus appropriée, car EntrySet supprime également les valeurs inutiles, ce qui gaspille des performances et de l'espace. Dans les résultats des tests ci-dessus, keySet prend 23 % de temps en moins que la méthode EntrySet.
3. Lorsque vous traversez uniquement une valeur, l'utilisation de la méthode vlaues est le meilleur choix, EntrySet est légèrement meilleur que la méthode keySet.
4. Parmi les différentes méthodes d'écriture traversante, il est recommandé d'utiliser la méthode d'écriture suivante, qui est légèrement plus efficace :
Copiez le code comme suit :
pour (clé de chaîne : map.keySet()) {
valeur = map.get(clé);
}
pour (entrée Entry<String, String> : map.entrySet()) {
clé = entrée.getKey();
valeur = entrée.getValue();
}
pour (Valeur de chaîne : map.values()) {
}
3.2 Si vous utilisez TreeMap
1. Lors du parcours simultané de la clé et de la valeur, contrairement à HashMap, les performances d'entrySet sont bien supérieures à celles de keySet. Ceci est déterminé par l'efficacité des requêtes de TreeMap. En d'autres termes, le coût de recherche de valeur dans TreeMap est relativement élevé, ce qui est nettement supérieur au coût de récupération de toutes les clés et valeurs à la fois à partir d'entrySet. Par conséquent, il est fortement recommandé d’utiliser la méthode EntrySet lors du parcours d’un TreeMap.
2. Lorsque vous parcourez uniquement des clés, la méthode keySet est plus appropriée, car EntrySet supprime également les valeurs inutiles, ce qui gaspille des performances et de l'espace. Dans les résultats des tests ci-dessus, keySet prend 24 % de temps en moins que la méthode EntrySet.
3. Lorsque vous traversez uniquement une valeur, l'utilisation de la méthode vlaues est le meilleur choix, et EntrySet est également évidemment meilleur que la méthode keySet.
4. Parmi les différentes méthodes d'écriture traversante, il est recommandé d'utiliser la méthode d'écriture suivante, qui est légèrement plus efficace :
Copiez le code comme suit :
pour (clé de chaîne : map.keySet()) {
valeur = map.get(clé);
}
pour (entrée Entry<String, String> : map.entrySet()) {
clé = entrée.getKey();
valeur = entrée.getValue();
}
pour (Valeur de chaîne : map.values()) {
}