Jak sprawnie iterować każdy wpis na mapie Javy?

Jeśli mam obiekt implementujący interfejs Map w Javie i chcę iterację nad każdą parą w nim zawartą, jaki jest najbardziej efektywny sposób przechodzenia przez mapę?

Czy kolejność elementów zależy od konkretnej implementacji mapy, którą mam dla interfejsu?

Author: Barry Chapman, 2008-09-05

30 answers

Map<String, String> map = ...
for (Map.Entry<String, String> entry : map.entrySet()) {
    System.out.println(entry.getKey() + "/" + entry.getValue());
}
 5283
Author: ScArcher2,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-14 22:20:24

Aby podsumować Pozostałe odpowiedzi i połączyć je z tym, co wiem, znalazłem 10 głównych sposobów, aby to zrobić (patrz poniżej). Napisałem też kilka testów wydajnościowych(patrz wyniki poniżej). Na przykład, jeśli chcemy znaleźć sumę wszystkich kluczy i wartości mapy, możemy napisać:

  1. Za pomocą iteratora i Mapy.Wpis

    long i = 0;
    Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry<Integer, Integer> pair = it.next();
        i += pair.getKey() + pair.getValue();
    }
    
  2. Używając foreach i Mapy.Wpis

    long i = 0;
    for (Map.Entry<Integer, Integer> pair : map.entrySet()) {
        i += pair.getKey() + pair.getValue();
    }
    
  3. Using forEach from Java 8

    final long[] i = {0};
    map.forEach((k, v) -> i[0] += k + v);
    
  4. Using keySet and foreach

    long i = 0;
    for (Integer key : map.keySet()) {
        i += key + map.get(key);
    }
    
  5. Using keySet and iterator

    long i = 0;
    Iterator<Integer> itr2 = map.keySet().iterator();
    while (itr2.hasNext()) {
        Integer key = itr2.next();
        i += key + map.get(key);
    }
    
  6. Używając dla i Mapy.Wpis

    long i = 0;
    for (Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator(); entries.hasNext(); ) {
        Map.Entry<Integer, Integer> entry = entries.next();
        i += entry.getKey() + entry.getValue();
    }
    
  7. Korzystanie z Java 8 Stream API

    final long[] i = {0};
    map.entrySet().stream().forEach(e -> i[0] += e.getKey() + e.getValue());
    
  8. Korzystanie z Java 8 Stream API parallel

    final long[] i = {0};
    map.entrySet().stream().parallel().forEach(e -> i[0] += e.getKey() + e.getValue());
    
  9. Using IterableMap of Apache Collections

    long i = 0;
    MapIterator<Integer, Integer> it = iterableMap.mapIterator();
    while (it.hasNext()) {
        i += it.next() + it.getValue();
    }
    
  10. Użycie MutableMap kolekcji Eclipse (CS)

    final long[] i = {0};
    mutableMap.forEachKeyValue((key, value) -> {
        i[0] += key + value;
    });
    

Testy wydajności (mode = AverageTime, system = Windows 8.1 64-bit, Intel i7 - 4790 3.60 GHz, 16 GB)

  1. Dla małej mapy (100 elementów) wynik 0,308 jest najlepszy

    Benchmark                          Mode  Cnt  Score    Error  Units
    test3_UsingForEachAndJava8         avgt  10   0.308 ±  0.021  µs/op
    test10_UsingEclipseMap             avgt  10   0.309 ±  0.009  µs/op
    test1_UsingWhileAndMapEntry        avgt  10   0.380 ±  0.014  µs/op
    test6_UsingForAndIterator          avgt  10   0.387 ±  0.016  µs/op
    test2_UsingForEachAndMapEntry      avgt  10   0.391 ±  0.023  µs/op
    test7_UsingJava8StreamApi          avgt  10   0.510 ±  0.014  µs/op
    test9_UsingApacheIterableMap       avgt  10   0.524 ±  0.008  µs/op
    test4_UsingKeySetAndForEach        avgt  10   0.816 ±  0.026  µs/op
    test5_UsingKeySetAndIterator       avgt  10   0.863 ±  0.025  µs/op
    test8_UsingJava8StreamApiParallel  avgt  10   5.552 ±  0.185  µs/op
    
  2. Dla mapy z 10000 elementów, wynik 37.606 jest najlepszy

    Benchmark                           Mode   Cnt  Score      Error   Units
    test10_UsingEclipseMap              avgt   10    37.606 ±   0.790  µs/op
    test3_UsingForEachAndJava8          avgt   10    50.368 ±   0.887  µs/op
    test6_UsingForAndIterator           avgt   10    50.332 ±   0.507  µs/op
    test2_UsingForEachAndMapEntry       avgt   10    51.406 ±   1.032  µs/op
    test1_UsingWhileAndMapEntry         avgt   10    52.538 ±   2.431  µs/op
    test7_UsingJava8StreamApi           avgt   10    54.464 ±   0.712  µs/op
    test4_UsingKeySetAndForEach         avgt   10    79.016 ±  25.345  µs/op
    test5_UsingKeySetAndIterator        avgt   10    91.105 ±  10.220  µs/op
    test8_UsingJava8StreamApiParallel   avgt   10   112.511 ±   0.365  µs/op
    test9_UsingApacheIterableMap        avgt   10   125.714 ±   1.935  µs/op
    
  3. Dla mapy z 100000 elementów, wynik 1184.767 jest the best

    Benchmark                          Mode   Cnt  Score        Error    Units
    test1_UsingWhileAndMapEntry        avgt   10   1184.767 ±   332.968  µs/op
    test10_UsingEclipseMap             avgt   10   1191.735 ±   304.273  µs/op
    test2_UsingForEachAndMapEntry      avgt   10   1205.815 ±   366.043  µs/op
    test6_UsingForAndIterator          avgt   10   1206.873 ±   367.272  µs/op
    test8_UsingJava8StreamApiParallel  avgt   10   1485.895 ±   233.143  µs/op
    test5_UsingKeySetAndIterator       avgt   10   1540.281 ±   357.497  µs/op
    test4_UsingKeySetAndForEach        avgt   10   1593.342 ±   294.417  µs/op
    test3_UsingForEachAndJava8         avgt   10   1666.296 ±   126.443  µs/op
    test7_UsingJava8StreamApi          avgt   10   1706.676 ±   436.867  µs/op
    test9_UsingApacheIterableMap       avgt   10   3289.866 ±  1445.564  µs/op
    

Wykresy (testy wydajności w zależności od wielkości mapy)

Tutaj wpisz opis obrazka

Tabela (testy wydajności w zależności od wielkości mapy)

          100     600      1100     1600     2100
test10    0.333    1.631    2.752    5.937    8.024
test3     0.309    1.971    4.147    8.147   10.473
test6     0.372    2.190    4.470    8.322   10.531
test1     0.405    2.237    4.616    8.645   10.707
test2     0.376    2.267    4.809    8.403   10.910
test7     0.473    2.448    5.668    9.790   12.125
test9     0.565    2.830    5.952   13.220   16.965
test4     0.808    5.012    8.813   13.939   17.407
test5     0.810    5.104    8.533   14.064   17.422
test8     5.173   12.499   17.351   24.671   30.403

Wszystkie testy są na GitHub .

 1325
Author: Slava Vedenin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-05 20:12:22

W Javie 8 możesz to zrobić czysto i szybko, korzystając z nowych funkcji lambda:

 Map<String,String> map = new HashMap<>();
 map.put("SomeKey", "SomeValue");
 map.forEach( (k,v) -> [do something with key and value] );

 // such as
 map.forEach( (k,v) -> System.out.println("Key: " + k + ": Value: " + v));

Typ k i v zostanie wywnioskowany przez kompilator i nie ma już potrzeby używania Map.Entry.

Łatwizna!
 308
Author: The Coordinator,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-07 08:33:17

Tak, kolejność zależy od konkretnej implementacji Mapy.

@ScArcher2 posiada bardziej elegancką składnię Java 1.5 . W 1.4 zrobiłbym coś takiego:

Iterator entries = myMap.entrySet().iterator();
while (entries.hasNext()) {
  Entry thisEntry = (Entry) entries.next();
  Object key = thisEntry.getKey();
  Object value = thisEntry.getValue();
  // ...
}
 251
Author: pkaeding,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-06 22:32:29

Typowy kod do iteracji na mapie to:

Map<String,Thing> map = ...;
for (Map.Entry<String,Thing> entry : map.entrySet()) {
    String key = entry.getKey();
    Thing thing = entry.getValue();
    ...
}

HashMap jest kanoniczną implementacją map i nie daje gwarancji (lub chociaż nie powinna zmieniać kolejności, jeśli na niej nie są wykonywane żadne operacje mutacyjne). SortedMap zwróci wpisy w oparciu o naturalną kolejność kluczy, lub Comparator, jeśli jest to przewidziane. LinkedHashMap zwróci wpisy w kolejności wstawiania lub w kolejności dostępu w zależności od sposobu ich budowy. EnumMap zwraca wpisy w naturalnej kolejności klucze.

(Aktualizacja: myślę, że to już nie jest prawda.) uwaga, IdentityHashMap entrySet iterator posiada obecnie osobliwą implementację, która zwraca tę samą instancję Map.Entry dla każdego elementu w entrySet! Jednak za każdym razem, gdy nowy iterator awansuje Map.Entry jest aktualizowany.

 141
Author: Tom Hawtin - tackline,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-09 01:11:36

Przykład użycia iteratora i generyków:

Iterator<Map.Entry<String, String>> entries = myMap.entrySet().iterator();
while (entries.hasNext()) {
  Map.Entry<String, String> entry = entries.next();
  String key = entry.getKey();
  String value = entry.getValue();
  // ...
}
 126
Author: serg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-18 17:34:51

Jest to pytanie dwuczęściowe:

Jak iterować nad wpisami na mapie - @ ScArcher2 odpowiedział że doskonale.

Jaka jest kolejność iteracji - jeśli używasz tylko Map, to ściśle mówiąc, nie ma żadnych gwarancji porządkowania . Więc tak naprawdę nie powinieneś polegać na zamówieniu podanym przez jakąkolwiek realizację. Jednak SortedMap interfejs rozszerza Map i zapewnia dokładnie to, czego szukasz - implementacje dadzą spójną kolejność sortowania.

NavigableMap jest kolejnym przydatnym rozszerzeniem - jest to SortedMap z dodatkowymi metodami znajdowania wpisów według ich uporządkowanej pozycji w zestawie kluczy. Więc potencjalnie może to usunąć potrzebę iteracji w pierwszej kolejności - możesz być w stanie znaleźć konkretny entry, który jesteś po użyciu higherEntry, lowerEntry, ceilingEntry, lub floorEntry metody. Metoda descendingMap daje nawet jawną metodę odwracania kolejność przejazdu .

 104
Author: serg10,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:32

Jest kilka sposobów na iterację mapy.

Oto porównanie ich wydajności dla wspólnego zestawu danych przechowywanych w map przez przechowywanie milionów par wartości klucza w map i będzie iteracją ponad mapą.

1) Użycie entrySet() in dla każdej pętli

for (Map.Entry<String,Integer> entry : testMap.entrySet()) {
    entry.getKey();
    entry.getValue();
}

50 milisekundy

2) Użycie keySet() in dla każdej pętli

for (String key : testMap.keySet()) {
    testMap.get(key);
}

76 milisekundy

3) Używanie entrySet() i iteratora

Iterator<Map.Entry<String,Integer>> itr1 = testMap.entrySet().iterator();
while(itr1.hasNext()) {
    Map.Entry<String,Integer> entry = itr1.next();
    entry.getKey();
    entry.getValue();
}

50 milisekundy

4) Używanie keySet() i iteratora

Iterator itr2 = testMap.keySet().iterator();
while(itr2.hasNext()) {
    String key = itr2.next();
    testMap.get(key);
}

75 milisekundy

Odnieśli this link.

 86
Author: Darshan Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-18 15:58:26

Poprawnym sposobem, aby to zrobić, jest użycie zaakceptowanej odpowiedzi, ponieważ jest ona najbardziej skuteczna. Uważam, że poniższy kod wygląda nieco czystsze.

for (String key: map.keySet()) {
   System.out.println(key + "/" + map.get(key));
}
 60
Author: Chris Dail,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-17 00:16:44

Dla twojej wiadomości, możesz również użyć map.keySet() i map.values() jeśli interesują Cię tylko klucze/wartości mapy, a nie inne.

 59
Author: ckpwong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-05 22:27:52

Za pomocą Java 8 można iterować mapę używając wyrażenia forEach i lambda,

map.forEach((k, v) -> System.out.println((k + ":" + v)));
 49
Author: Taras Melnyk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-15 09:09:30

Z kolekcjami Eclipse , można użyć metody forEachKeyValue na MapIterable interfejs, który jest dziedziczony przez interfejsy MutableMap i ImmutableMap i ich implementacje.

MutableBag<String> result = Bags.mutable.empty();
MutableMap<Integer, String> map = Maps.mutable.of(1, "One", 2, "Two", 3, "Three");
map.forEachKeyValue((key, value) -> result.add(key + value));
Assert.assertEquals(Bags.mutable.of("1One", "2Two", "3Three"), result);

Używając anonimowej klasy wewnętrznej, możesz napisać kod w następujący sposób:

final MutableBag<String> result = Bags.mutable.empty();
MutableMap<Integer, String> map = Maps.mutable.of(1, "One", 2, "Two", 3, "Three");
map.forEachKeyValue(new Procedure2<Integer, String>()
{
    public void value(Integer key, String value)
    {
        result.add(key + value);
    }
});
Assert.assertEquals(Bags.mutable.of("1One", "2Two", "3Three"), result);

Notatka: jestem committerem Dla Kolekcji Eclipse.

 42
Author: Donald Raab,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-13 19:49:46

W teorii, najbardziej efektywny sposób będzie zależał od tego, która implementacja Mapy. Oficjalnym sposobem na to jest wywołanie map.entrySet(), które zwraca zbiór Map.Entry, z których każdy zawiera klucz i wartość (entry.getKey() i entry.getValue()).

W idiosynkratycznej implementacji może mieć znaczenie, czy używasz map.keySet(), map.entrySet() albo coś innego. Ale nie mogę wymyślić powodu, dla którego ktoś miałby to tak pisać. Najprawdopodobniej nie ma różnicy w wydajności tego, co robisz.

I tak, kolejność będzie zależeć od implementacji - a także (ewentualnie) kolejności wstawiania i innych trudnych do kontrolowania czynników.

[edytuj] pisałem valueSet() pierwotnie, ale oczywiście entrySet() jest właściwie odpowiedzią.

 37
Author: Leigh Caldwell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-04 22:39:46

Lambda Wyrażenie Java 8

W Javie 1.8 (Java 8) stało się to znacznie łatwiejsze dzięki zastosowaniu metody forEach z operacji Agregacyjnych (Stream operations), która wygląda podobnie do iteratorów z interfejsu Iterable.

Po prostu skopiuj wklej poniższą instrukcję do kodu i zmień nazwę zmiennej HashMap z hm na zmienną HashMap, aby wydrukować parę klucz-wartość.

HashMap<Integer,Integer> hm = new HashMap<Integer, Integer>();
/*
 *     Logic to put the Key,Value pair in your HashMap hm
 */

// Print the key value pair in one line.

hm.forEach((k, v) -> System.out.println("key: " + k + " value:" + v));

// Just copy and paste above line to your code.

Poniżej znajduje się przykładowy kod, który próbowałem używając wyrażenia Lambda. To jest takie fajne. Muszę spróbować.

HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
    Random rand = new Random(47);
    int i = 0;
    while(i < 5) {
        i++;
        int key = rand.nextInt(20);
        int value = rand.nextInt(50);
        System.out.println("Inserting key: " + key + " Value: " + value);
        Integer imap = hm.put(key, value);
        if( imap == null) {
            System.out.println("Inserted");
        } else {
            System.out.println("Replaced with " + imap);
        }               
    }

    hm.forEach((k, v) -> System.out.println("key: " + k + " value:" + v));

Output:

Inserting key: 18 Value: 5
Inserted
Inserting key: 13 Value: 11
Inserted
Inserting key: 1 Value: 29
Inserted
Inserting key: 8 Value: 0
Inserted
Inserting key: 2 Value: 7
Inserted
key: 1 value:29
key: 18 value:5
key: 2 value:7
key: 8 value:0
key: 13 value:11

Również można użyć Spliterator do tego samego.

Spliterator sit = hm.entrySet().spliterator();

UPDATE


Wraz z odnośnikami do dokumentacji Oracle Docs. Aby dowiedzieć się więcej o Lambda wejdź w ten link i przeczytaj operacje zbiorcze , A Dla Spliteratora przejdź do tego link .

 37
Author: Nitin Mahesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-04-30 13:05:59

Java 8

Mamy metodę forEach, która przyjmuje wyrażenie lambda. Mamy również API stream. Rozważmy mapę:

Map<String,String> sample = new HashMap<>();
sample.put("A","Apple");
sample.put("B", "Ball");

Iteracja nad kluczami:

sample.keySet().forEach((k) -> System.out.println(k));

Iteracja nad wartościami:

sample.values().forEach((v) -> System.out.println(v));

Iteracja nad wpisami (za pomocą forEach i strumieni):

sample.forEach((k,v) -> System.out.println(k + ":" + v)); 
sample.entrySet().stream().forEach((entry) -> {
            Object currentKey = entry.getKey();
            Object currentValue = entry.getValue();
            System.out.println(currentKey + ":" + currentValue);
        });

Zaletą strumieni jest to, że mogą być łatwo równoległe w przypadku, gdy chcemy. Po prostu musimy użyć parallelStream() zamiast stream() powyżej.

forEachOrdered vs forEach ze strumieniami ? forEach nie jest zgodny z porządkiem spotkania (jeśli jest zdefiniowany) i jest z natury niedeterministyczny, gdzie tak jak forEachOrdered. Więc forEach nie gwarantuje, że zamówienie zostanie zachowane. Sprawdź również to , aby uzyskać więcej.

 36
Author: akhil_mittal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-04-29 05:52:35

Java 8:

Możesz używać wyrażeń lambda:

myMap.entrySet().stream().forEach((entry) -> {
    Object currentKey = entry.getKey();
    Object currentValue = entry.getValue();
});

Aby uzyskać więcej informacji, wykonaj to .

 33
Author: George Siggouroglou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-06 03:37:46

Spróbuj z Javą 1.4:

for( Iterator entries = myMap.entrySet().iterator(); entries.hasNext();){

  Entry entry = (Entry) entries.next();

  System.out.println(entry.getKey() + "/" + entry.getValue());

  //...
}
 29
Author: abods,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-07 14:34:44

W Mapach można iterację nad keys i / lub values i / lub both (e.g., entrySet) zależy od zainteresowania_ jak:

  1. Iterować przez keys -> keySet() z mapy:

     Map<String, Object> map = ...;
    
     for (String key : map.keySet()) {
         //your Business logic...
     }
    
  2. Iterować przez values -> values() z mapy:

     for (Object value : map.values()) {
         //your Business logic...
     }
    
  3. Iterować przez both -> entrySet() z mapy:

     for (Map.Entry<String, Object> entry : map.entrySet()) {
         String key = entry.getKey();
         Object value = entry.getValue();
         //your Business logic...
     }
    

Ponadto istnieją 3 różne sposoby iteracji za pomocą Hashmapy. Są one jak poniżej:

//1.
for (Map.Entry entry : hm.entrySet()) {
    System.out.print("key,val: ");
    System.out.println(entry.getKey() + "," + entry.getValue());
}

//2.
Iterator iter = hm.keySet().iterator();
while(iter.hasNext()) {
    Integer key = (Integer)iter.next();
    String val = (String)hm.get(key);
    System.out.println("key,val: " + key + "," + val);
}

//3.
Iterator it = hm.entrySet().iterator();
while (it.hasNext()) {
    Map.Entry entry = (Map.Entry) it.next();
    Integer key = (Integer)entry.getKey();
    String val = (String)entry.getValue();
    System.out.println("key,val: " + key + "," + val);
}
 28
Author: Rupesh Yadav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-30 15:21:24

Najbardziej kompaktowy z Java 8:

map.entrySet().forEach(System.out::println);
 24
Author: bluehallu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-19 12:32:20

Jeśli posiadasz mapę generyczną, możesz użyć:

Map map = new HashMap();
for (Map.Entry entry : ((Set<Map.Entry>) map.entrySet())) {
    System.out.println(entry.getKey() + "/" + entry.getValue());
}
 21
Author: dmunozfer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-16 16:17:58
public class abcd{
    public static void main(String[] args)
    {
       Map<Integer, String> testMap = new HashMap<Integer, String>();
        testMap.put(10, "a");
        testMap.put(20, "b");
        testMap.put(30, "c");
        testMap.put(40, "d");
        for (Integer key:testMap.keySet()) {
            String value=testMap.get(key);
            System.out.println(value);
        }
    }
}

Lub

public class abcd {
    public static void main(String[] args)
    {
       Map<Integer, String> testMap = new HashMap<Integer, String>();
        testMap.put(10, "a");
        testMap.put(20, "b");
        testMap.put(30, "c");
        testMap.put(40, "d");
        for (Entry<Integer, String> entry : testMap.entrySet()) {
            Integer key=entry.getKey();
            String value=entry.getValue();
        }
    }
}
 20
Author: Fathah Rehman P,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-07 14:34:13

Jeśli mam obiekt implementujący interfejs mapy w Javie i chcę iterację nad każdą parą w nim zawartą, jaki jest najbardziej efektywny sposób przechodzenia przez mapę?

Jeśli wydajność zapętlania kluczy jest priorytetem dla Twojej aplikacji, wybierz implementację Map, która utrzymuje klucze w żądanej kolejności.

Czy kolejność elementów zależy od konkretnej implementacji mapy, którą mam dla interfejs?

Tak, oczywiście.
  • niektóre implementacje Map obiecują pewną kolejność iteracji, inne nie.
  • różne implementacje Map zachowują różną kolejność par klucz-wartość.

Zobacz tabelę, którą stworzyłem podsumowując różne implementacje Map w pakiecie z Java 11. W szczególności zwróć uwagę na kolumnę porządku iteracji . Kliknij / stuknij, aby powiększyć.

Tabela implementacji map w Javie 11, porównująca ich funkcje

Widzisz istnieją cztery implementacje utrzymujące porządek :

  • TreeMap
  • ConcurrentSkipListMap
  • LinkedHashMap
  • EnumMap

NavigableMap interfejs

Dwa z nich realizują NavigableMap interfejs: TreeMap & ConcurrentSkipListMap.

The older SortedMap interfejs jest skutecznie wypierany przez nowsze NavigableMap interfejs. Ale możesz znaleźć implementacje innych firm implementujące tylko starszy interfejs.

Naturalne zamówienie

Jeśli chcesz Map która utrzymuje swoje pary ułożone według "naturalnego porządku" klucza, użyj TreeMap lub ConcurrentSkipListMap. Termin "porządek naturalny" oznacza klasę klawiszy Comparable. Wartość zwracana przez compareTo metoda jest używana do porównywania w sortowaniu.

Zamówienie na zamówienie

Jeśli chcesz określić niestandardową procedurę sortowania dla kluczy, które mają być używane do utrzymywania sortowanego porządku, podaj Comparator implementacja odpowiednia do klasy Twoich kluczy. Użyj albo TreeMap lub ConcurrentSkipListMap, mijając swoje Comparator.

Oryginalna kolejność wstawiania

Jeśli chcesz, aby pary twojej mapy były utrzymywane w pierwotnej kolejności, w jakiej je wstawiłeś do mapy, użyj LinkedHashMap.

Enum-porządek definicji

Jeśli używasz enum, takiego jak DayOfWeek lub Month jako swoje klucze, użyj EnumMap klasy. Nie tylko ta klasa jest wysoce zoptymalizowana tak, aby zużywała bardzo mało pamięci i działała bardzo szybko, ale utrzymuje pary w kolejności określonej przez enum. Dla DayOfWeek, na przykład, klucz DayOfWeek.MONDAY zostanie znaleziony po iteracji, a klucz DayOfWeek.SUNDAY będzie ostatni.

Inne względy

Wybierając implementację Map należy również wziąć pod uwagę:

  • NULLs. Niektóre implementacje zabraniają / akceptują NULL jako klucz i / lub wartość.
  • współbieżność. Jeśli manipulując mapą między wątkami, musisz użyć implementacji obsługującej współbieżność. Lub zawinąć mapę z Collections::synchronizedMap (mniej korzystne).

Obie te kwestie zostały omówione w powyższej tabeli graficznej.

 20
Author: Basil Bourque,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-13 05:39:06

Kolejność zawsze zależy od konkretnej implementacji mapy. W Javie 8 można użyć jednego z następujących elementów:

map.forEach((k,v) -> { System.out.println(k + ":" + v); });

Lub:

map.entrySet().forEach((e) -> {
            System.out.println(e.getKey() + " : " + e.getValue());
        });

Wynik będzie taki sam (ta sama kolejność). EntrySet wspierany przez mapę, więc dostajesz tę samą kolejność. Drugi jest przydatny, ponieważ pozwala na używanie lambda, np. jeśli chcesz drukować tylko obiekty całkowite, które są większe niż 5:

map.entrySet()
    .stream()
    .filter(e-> e.getValue() > 5)
    .forEach(System.out::println);

Poniższy kod pokazuje iterację poprzez LinkedHashMap i normalną Hashmapę (przykład). Ty zobaczy różnicę w kolejności:

public class HMIteration {


    public static void main(String[] args) {
        Map<Object, Object> linkedHashMap = new LinkedHashMap<>();
        Map<Object, Object> hashMap = new HashMap<>();

        for (int i=10; i>=0; i--) {
            linkedHashMap.put(i, i);
            hashMap.put(i, i);
        }

        System.out.println("LinkedHashMap (1): ");
        linkedHashMap.forEach((k,v) -> { System.out.print(k + " (#="+k.hashCode() + "):" + v + ", "); });

        System.out.println("\nLinkedHashMap (2): ");

        linkedHashMap.entrySet().forEach((e) -> {
            System.out.print(e.getKey() + " : " + e.getValue() + ", ");
        });


        System.out.println("\n\nHashMap (1): ");
        hashMap.forEach((k,v) -> { System.out.print(k + " (#:"+k.hashCode() + "):" + v + ", "); });

        System.out.println("\nHashMap (2): ");

        hashMap.entrySet().forEach((e) -> {
            System.out.print(e.getKey() + " : " + e.getValue() + ", ");
        });
    }
}

Wyjście:

LinkedHashMap (1):
10 (#=10):10, 9 (#=9):9, 8 (#=8):8, 7 (#=7):7, 6 (#=6):6, 5 (#=5):5, 4 (#=4):4, 3 (#=3):3, 2 (#=2):2, 1 (#=1):1, 0 (#=0):0,
LinkedHashMap (2):
10 : 10, 9 : 9, 8 : 8, 7 : 7, 6 : 6, 5 : 5, 4 : 4, 3 : 3, 2 : 2, 1 : 1, 0 : 0,
HashMap (1):
0 (#:0):0, 1 (#:1):1, 2 (#:2):2, 3 (#:3):3, 4 (#:4):4, 5 (#:5):5, 6 (#:6):6, 7 (#:7):7, 8 (#:8):8, 9 (#:9):9, 10 (#:10):10,
HashMap (2):
0 : 0, 1 : 1, 2 : 2, 3 : 3, 4 : 4, 5 : 5, 6 : 6, 7 : 7, 8 : 8, 9 : 9, 10 : 10,
 19
Author: Witold Kaczurba,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-30 17:26:53
    Iterator iterator = map.entrySet().iterator();
    while (iterator.hasNext()) {
        Map.Entry element = (Map.Entry)it.next();
        LOGGER.debug("Key: " + element.getKey());
        LOGGER.debug("value: " + element.getValue());    
    }
 15
Author: Fadid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-14 20:58:30

Możesz to zrobić używając generyków:

Map<Integer, Integer> map = new HashMap<Integer, Integer>();
Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator();
while (entries.hasNext()) {
    Map.Entry<Integer, Integer> entry = entries.next();
    System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}
 14
Author: Pranoti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-16 15:54:24

Użyj Javy 8:

map.entrySet().forEach(entry -> System.out.println(entry.getValue()));
 14
Author: ABHAY JOHRI,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-17 19:03:40

Efektywnym rozwiązaniem iteracyjnym nad mapą jest pętla for od Javy 5 do Javy 7. Tutaj jest:

for (String key : phnMap.keySet()) {
    System.out.println("Key: " + key + " Value: " + phnMap.get(key));
}

W Javie 8 można używać wyrażenia lambda do iteracji na mapie. Jest to wzmocnione forEach

phnMap.forEach((k,v) -> System.out.println("Key: " + k + " Value: " + v));

Jeśli chcesz napisać warunkową dla lambda, możesz napisać ją w następujący sposób:

phnMap.forEach((k,v)->{
    System.out.println("Key: " + k + " Value: " + v);
    if("abc".equals(k)){
        System.out.println("Hello abc");
    }
});
 12
Author: anandchaugule,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-30 12:08:36
           //Functional Oprations
            Map<String, String> mapString = new HashMap<>();
            mapString.entrySet().stream().map((entry) -> {
                String mapKey = entry.getKey();
                return entry;
            }).forEach((entry) -> {
                String mapValue = entry.getValue();
            });

            //Intrator
            Map<String, String> mapString = new HashMap<>();
            for (Iterator<Map.Entry<String, String>> it = mapString.entrySet().iterator(); it.hasNext();) {
                Map.Entry<String, String> entry = it.next();
                String mapKey = entry.getKey();
                String mapValue = entry.getValue();
            }

            //Simple for loop
            Map<String, String> mapString = new HashMap<>();
            for (Map.Entry<String, String> entry : mapString.entrySet()) {
                String mapKey = entry.getKey();
                String mapValue = entry.getValue();

            }
 11
Author: Sajad NasiriNezhad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-13 07:47:46

Tak, jak wiele osób zgodziło się, że jest to najlepszy sposób na iterację Map.

Ale są szanse rzucić nullpointerexception jeśli mapa jest null. Nie zapomnij umieścić null .zgłoś się.

                                                 |
                                                 |
                                         - - - -
                                       |
                                       |
for (Map.Entry<String, Object> entry : map.entrySet()) {
    String key = entry.getKey();
    Object value = entry.getValue();
}
 10
Author: Suresh Atta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-06 22:40:17

Jest na to wiele sposobów. Poniżej kilka prostych kroków:

Załóżmy, że masz jedną mapę typu:

Map<String, Integer> m = new HashMap<String, Integer>();

Następnie możesz zrobić coś takiego jak poniżej, aby iterację elementów mapy.

// ********** Using an iterator ****************
Iterator<Entry<String, Integer>> me = m.entrySet().iterator();
while(me.hasNext()){
    Entry<String, Integer> pair = me.next();
    System.out.println(pair.getKey() + ":" + pair.getValue());
}

// *********** Using foreach ************************
for(Entry<String, Integer> me : m.entrySet()){
    System.out.println(me.getKey() + " : " + me.getValue());
}

// *********** Using keySet *****************************
for(String s : m.keySet()){
    System.out.println(s + " : " + m.get(s));
}

// *********** Using keySet and iterator *****************
Iterator<String> me = m.keySet().iterator();
while(me.hasNext()){
    String key = me.next();
    System.out.println(key + " : " + m.get(key));
}
 10
Author: Utpal Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-22 10:10:05