1. Erklärung
In Bezug auf die Map-Traversal-Methode in Java empfehlen viele Artikel die Verwendung von EntrySet, das als wesentlich effizienter als KeySet gilt. Der Grund dafür ist: Die Methode „entrySet“ ruft die Menge aller Schlüssel und Werte auf einmal ab, während die Methode „keySet“ nur die Menge der Schlüssel abruft. Für jeden Schlüssel muss der Wert noch einmal in der Map gesucht werden, wodurch die Menge reduziert wird Gesamteffizienz. Wie ist also die aktuelle Situation?
Um die tatsächliche Lücke in der Durchlaufleistung zu verstehen, einschließlich der Unterschiede in verschiedenen Szenarien wie Durchlaufen von Schlüssel + Wert, Durchlaufen von Schlüssel, Durchlaufen von Wert usw., habe ich versucht, einige Vergleichstests durchzuführen.
2. Vergleichstests
Zuerst wurde nur ein einfacher Test durchgeführt, aber die Ergebnisse zeigten, dass die Leistung von keySet besser war, was mich verwirrte. Sagen sie nicht alle, dass EntrySet offensichtlich besser ist als KeySet? Zur weiteren Verifizierung wurden unterschiedliche Testdaten für detailliertere Vergleichstests herangezogen.
2.1 Testdaten
2.1.1 HashMap-Testdaten
HashMap-1, die Größe beträgt 1 Million, der Schlüssel und der Wert sind beide String, der Schlüsselwert ist 1, 2, 3 ... 1000000:
Kopieren Sie den Codecode wie folgt:
Map<String, String> map = new HashMap<String, String>();
String-Schlüssel, Wert;
for (i = 1; i <= num; i++) {
key = "" + i;
Wert = "Wert";
map.put(key, value);
}
HashMap-2, die Größe beträgt 1 Million, der Schlüssel und der Wert sind beide String, der Schlüsselwert ist 50, 100, 150, 200, ..., 50000000:
Kopieren Sie den Codecode wie folgt:
Map<String, String> map = new HashMap<String, String>();
String-Schlüssel, Wert;
for (i = 1; i <= num; i++) {
key = "" + (i * 50);
Wert = "Wert";
map.put(key, value);
}
2.1.2 TreeMap-Testdaten
TreeMap-1, die Größe beträgt 1 Million, der Schlüssel und der Wert sind beide String, der Schlüsselwert ist 1, 2, 3 ... 1000000:
Kopieren Sie den Codecode wie folgt:
Map<String, String> map = new TreeMap<String, String>();
String-Schlüssel, Wert;
for (i = 1; i <= num; i++) {
key = "" + i;
Wert = "Wert";
map.put(key, value);
}
TreeMap-2, die Größe beträgt 1 Million, der Schlüssel und der Wert sind beide String, die Schlüsselwerte sind 50, 100, 150, 200, ..., 50000000, diskreter:
Kopieren Sie den Codecode wie folgt:
Map<String, String> map = new TreeMap<String, String>();
String-Schlüssel, Wert;
for (i = 1; i <= num; i++) {
key = "" + (i * 50);
Wert = "Wert";
map.put(key, value);
}
2.2 Testszenario
Verwenden Sie verschiedene Schreibmethoden für KeySet, EntrySet und Values, um drei Szenarien zu testen: Durchlaufen von Schlüssel + Wert, Durchlaufen von Schlüssel und Durchlaufen von Werten.
2.2.1 Schlüssel+Wert durchqueren
keySet durchläuft Schlüssel+Wert (Schreibmethode 1):
Kopieren Sie den Codecode wie folgt:
Iterator<String> iter = map.keySet().iterator();
while (iter.hasNext()) {
key = iter.next();
value = map.get(key);
}
keySet durchläuft Schlüssel+Wert (Schreibmethode 2):
Kopieren Sie den Codecode wie folgt:
for (String key : map.keySet()) {
value = map.get(key);
}
EntrySet durchläuft Schlüssel+Wert (Schreibmethode 1):
Kopieren Sie den Codecode wie folgt:
Iterator<Entry<String, String>> iter = map.entrySet().iterator();
Eintrag<String, String> Eintrag;
while (iter.hasNext()) {
Eintrag = iter.next();
key = enter.getKey();
value = Eintrag.getValue();
}
EntrySet durchläuft Schlüssel+Wert (Schreibmethode 2):
Kopieren Sie den Codecode wie folgt:
for (Entry<String, String> Eintrag: map.entrySet()) {
key = enter.getKey();
value = Eintrag.getValue();
}
2.2.2 Verfahrtaste
keySet durchläuft den Schlüssel (Schreibmethode 1):
Kopieren Sie den Codecode wie folgt:
Iterator<String> iter = map.keySet().iterator();
while (iter.hasNext()) {
key = iter.next();
}
keySet durchläuft den Schlüssel (Schreibmethode 2):
Kopieren Sie den Codecode wie folgt:
for (String key : map.keySet()) {
}
EntrySet durchquert den Schlüssel (Schreibmethode 1):
Kopieren Sie den Codecode wie folgt:
Iterator<Entry<String, String>> iter = map.entrySet().iterator();
while (iter.hasNext()) {
key = iter.next().getKey();
}
EntrySet durchquert den Schlüssel (Schreibmethode 2):
Kopieren Sie den Codecode wie folgt:
for (Entry<String, String> Eintrag: map.entrySet()) {
key = enter.getKey();
}
2.2.3 Verfahrwert
keySet durchläuft den Wert (Schreibmethode 1):
Kopieren Sie den Codecode wie folgt:
Iterator<String> iter = map.keySet().iterator();
while (iter.hasNext()) {
value = map.get(iter.next());
}
keySet durchläuft den Wert (Schreibmethode 2):
Kopieren Sie den Codecode wie folgt:
for (String key : map.keySet()) {
value = map.get(key);
}
EntrySet durchläuft den Wert (Schreibmethode 1):
Kopieren Sie den Codecode wie folgt:
Iterator<Entry<String, String>> iter = map.entrySet().iterator();
while (iter.hasNext()) {
value = iter.next().getValue();
}
EntrySet durchläuft den Wert (Schreibmethode 2):
Kopieren Sie den Codecode wie folgt:
for (Entry<String, String> Eintrag: map.entrySet()) {
value = enter.getValue();
}
Werte durchqueren den Wert (Schreibmethode 1):
Kopieren Sie den Codecode wie folgt:
Iterator<String> iter = map.values().iterator();
while (iter.hasNext()) {
value = iter.next();
}
Werte durchqueren den Wert (Schreibmethode 2):
Kopieren Sie den Codecode wie folgt:
for (String value : map.values()) {
}
2.3 Testergebnisse
2.3.1 HashMap-Testergebnisse
Einheit: Millisekunde | HashMap-1 | HashMap-2 |
| keySet durchläuft Schlüssel+Wert (Schreibmethode 1) | 39 | 93 |
| keySet durchläuft Schlüssel+Wert (Schreibmethode 2) | 38 | 87 |
| EntrySet durchläuft Schlüssel+Wert (Schreibmethode 1) | 43 | 86 |
| EntrySet durchläuft Schlüssel+Wert (Schreibmethode 2) | 43 | 85 |
Einheit: Millisekunde | HashMap-1 | HashMap-2 |
| keySet durchquert den Schlüssel (Schreibmethode 1) | 27 | 65 |
| keySet durchquert den Schlüssel (Schreibmethode 2) | 26 | 64 |
| EntrySet durchquert den Schlüssel (Schreibmethode 1) | 35 | 75 |
| enterSet durchquert den Schlüssel (Schreibmethode 2) | 34 | 74 |
Einheit: Millisekunde | HashMap-1 | HashMap-2 |
| keySet durchläuft den Wert (Schreibmethode 1) | 38 | 87 |
| keySet durchläuft den Wert (Schreibmethode 2) | 37 | 87 |
| EntrySet durchläuft den Wert (Schreibmethode 1) | 34 | 61 |
| EntrySet durchläuft den Wert (Schreibmethode 2) | 32 | 62 |
| Werte durchlaufen den Wert (Schreibmethode 1) | 26 | 48 |
| Werte durchlaufen den Wert (Schreibmethode 2) | 26 | 48 |
2.3.2 TreeMap-Testergebnisse
Einheit: Millisekunde | TreeMap-1 | TreeMap-2 |
| keySet durchläuft Schlüssel+Wert (Schreibmethode 1) | 430 | 451 |
| keySet durchläuft Schlüssel+Wert (Schreibmethode 2) | 429 | 450 |
| EntrySet durchläuft Schlüssel+Wert (Schreibmethode 1) | 77 | 84 |
| EntrySet durchläuft Schlüssel+Wert (Schreibmethode 2) | 70 | 68 |
Einheit: Millisekunde | TreeMap-1 | TreeMap-2 |
| keySet durchquert den Schlüssel (Schreibmethode 1) | 50 | 49 |
| keySet durchquert den Schlüssel (Schreibmethode 2) | 49 | 48 |
| EntrySet durchquert den Schlüssel (Schreibmethode 1) | 66 | 64 |
| EntrySet durchquert den Schlüssel (Schreibmethode 2) | 65 | 63 |
Einheit: Millisekunde | TreeMap-1 | TreeMap-2 |
| keySet durchläuft den Wert (Schreibmethode 1) | 432 | 448 |
| keySet durchläuft den Wert (Schreibmethode 2) | 430 | 448 |
| EntrySet durchläuft den Wert (Schreibmethode 1) | 62 | 61 |
| EntrySet durchläuft den Wert (Schreibmethode 2) | 62 | 61 |
| Werte durchlaufen den Wert (Schreibmethode 1) | 46 | 46 |
| Werte durchlaufen den Wert (Schreibmethode 2) | 45 | 46 |
3. Fazit
3.1 Wenn Sie HashMap verwenden
1. Beim gleichzeitigen Durchlaufen von Schlüssel und Wert hängt der Leistungsunterschied zwischen den Methoden keySet und enterSet von den spezifischen Bedingungen des Schlüssels ab, z. B. Komplexität (komplexe Objekte), Diskretion, Konfliktrate usw. Mit anderen Worten, es hängt von den Kosten ab, die für die Suche nach Werten in HashMap anfallen. Der Vorgang von „entrySet“ zum gleichzeitigen Abrufen aller Schlüssel und Werte hat einen Leistungsaufwand zur Folge. Wenn dieser Verlust geringer ist als der Aufwand von HashMap bei der Suche nach Wert, spiegelt sich der Leistungsvorteil von „entrySet“ wider. Wenn der Schlüssel beispielsweise im obigen Vergleichstest die einfachste numerische Zeichenfolge ist, ist keySet möglicherweise effizienter und benötigt 10 % weniger Zeit als enterSet. Im Allgemeinen wird die Verwendung von EntrySet empfohlen. Denn wenn der Schlüssel sehr einfach ist, ist seine Leistung möglicherweise etwas geringer als die von keySet, aber er ist kontrollierbar, wenn der Schlüssel komplizierter wird, werden die Vorteile von EntrySet deutlich zum Ausdruck kommen. Natürlich können wir entsprechend der tatsächlichen Situation wählen
2. Wenn nur Schlüssel durchlaufen werden, ist die keySet-Methode besser geeignet, da enterSet auch nutzlose Werte herausnimmt, was Leistung und Platz verschwendet. In den obigen Testergebnissen benötigt keySet 23 % weniger Zeit als die enterSet-Methode.
3. Wenn nur der Wert durchlaufen wird, ist die Verwendung der vlaues-Methode die beste Wahl. EntrySet ist etwas besser als die keySet-Methode.
4. Unter den verschiedenen Traversal-Schreibmethoden wird empfohlen, die folgende Schreibmethode zu verwenden, die etwas effizienter ist:
Kopieren Sie den Codecode wie folgt:
for (String key : map.keySet()) {
value = map.get(key);
}
for (Entry<String, String> Eintrag: map.entrySet()) {
key = enter.getKey();
value = enter.getValue();
}
for (String-Wert: map.values()) {
}
3.2 Wenn Sie TreeMap verwenden
1. Beim gleichzeitigen Durchlaufen von Schlüssel und Wert ist die Leistung von EntrySet im Gegensatz zu HashMap viel höher als die von KeySet. Dies wird durch die Abfrageeffizienz von TreeMap bestimmt. Mit anderen Worten, die Kosten für die Suche nach Werten in TreeMap sind erheblich höher als die Kosten für das gleichzeitige Abrufen aller Schlüssel und Werte von EntrySet. Daher wird dringend empfohlen, beim Durchlaufen einer TreeMap die Methode „entrySet“ zu verwenden.
2. Wenn nur Schlüssel durchlaufen werden, ist die keySet-Methode besser geeignet, da enterSet auch nutzlose Werte herausnimmt, was Leistung und Platz verschwendet. In den obigen Testergebnissen benötigt keySet 24 % weniger Zeit als die enterSet-Methode.
3. Wenn nur Werte durchlaufen werden, ist die Verwendung der vlaues-Methode die beste Wahl, und enterSet ist offensichtlich auch besser als die keySet-Methode.
4. Unter den verschiedenen Traversal-Schreibmethoden wird empfohlen, die folgende Schreibmethode zu verwenden, die etwas effizienter ist:
Kopieren Sie den Codecode wie folgt:
for (String key : map.keySet()) {
value = map.get(key);
}
for (Entry<String, String> Eintrag: map.entrySet()) {
key = enter.getKey();
value = enter.getValue();
}
for (String value : map.values()) {
}