Pytanie w sprawie hashmap, iteration, java, loops – Iteruj przez HashMap [duplikat]

3059

Możliwy duplikat:
Jak skutecznie iterować po każdym wpisie w „Mapie”?

Jaki jest najlepszy sposób iteracji elementów wHashMap?

W Javie 8 za pomocą Lambda Expression:stackoverflow.com/a/25616206/1503859 Nitin Mahesh
Sprawdź odpowiedź :stackoverflow.com/a/53497541/5756557 anandchaugule
Muszę pobrać klucze i wartości i dodać je do tablicy wielowymiarowej burntsugar
@imibis prawdopodobnie dlatego, że wiele osób instynktownie używa HashMaps bez uwzględnienia innych implementacji map. Następnie, gdy nieuchronnie utkną, próbując przejrzeć swoją HashMap, uderzają „Iterate through a HashMap” w Google, prowadząc ich prosto tutaj. Dean Wild
Jak ma to wyższy wynik niż pytanie, które jest duplikatem? immibis

Twoja odpowiedź

7   odpowiedzi
4383

Jeśli interesują Cię tylko klucze, możesz iterować przezkeySet() mapy:

Map<String, Object> map = ...;

for (String key : map.keySet()) {
    // ...
}

Jeśli potrzebujesz tylko wartości, użyjvalues():

for (Object value : map.values()) {
    // ...
}

Wreszcie, jeśli chcesz zarówno klucz, jak i wartość, użyjentrySet():

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

Jedno zastrzeżenie: jeśli chcesz usunąć elementy w połowie iteracji, musisz to zrobić za pomocą Iteratora (zobaczodpowiedź karim79). Jednak zmiana wartości elementu jest OK (patrzMap.Entry).

Jeszcze jeden ważny punkt: zestaw zwrócony przez keySet () i Collection zwrócony przez value () jest wspierany przez oryginalną Mapę. Oznacza to, że jeśli dokonasz w nich jakiejkolwiek modyfikacji, zostaną one odzwierciedlone na Mapie, jednak oba nie obsługują metod add () i addAll (), tj. Nie możesz dodać nowego klucza do Set lub nowej wartości w kolekcji. sactiw
Więc jak zrobić pętlę przez dwie mapy jednocześnie? za pomocą metody entrySet? Próbowałem użyć &&, ale to działa DaMainBoss
Bardziej efektywne jest używanie entrySet, gdy potrzebujesz zarówno kluczy, jak i wartości. Jeśli potrzebujesz tylko jednego lub drugiego, użyj tego:stackoverflow.com/questions/3870064/… rogerdpack
O uzyskiwaniu zarówno wartości, jak i kluczy, łatwiej jest użyć pierwszegoforeach przykład i pobierz wartość wewnątrz pętli, za pomocąvalue = map.get(key)? Czy wydajnośćentrySet bardziej wysoki? Marco Sulla
115
for (Map.Entry<String, String> item : hashMap.entrySet()) {
    String key = item.getKey();
    String value = item.getValue();
}
@ChanjungKim tak, jest to nazwa HashMap heman123
Czy param jest nazwą HashMap? c-an
3020

Iteruj przezentrySet() w ten sposób:

public static void printMap(Map mp) {
    Iterator it = mp.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry pair = (Map.Entry)it.next();
        System.out.println(pair.getKey() + " = " + pair.getValue());
        it.remove(); // avoids a ConcurrentModificationException
    }
}

Przeczytaj więcej oMap.

OdMapa nie jest podIterator klasa,jak możesz użyć iteratora z mapą? Tylko lista, kolejka i zestaw są iterowalne. Rishabh Agarwal
@vimukthi co masz na myśli? Po prostu usuńit.remove(); linia. Danny
Wszyscy tak mówiąfor (Map.Entry<String, Object> cursor : map.entrySet()) jest lepsze niż ignorowanie faktu, że nadal otrzymaszConcurrentModificationException używając tej metody. Wybrana odpowiedź pozostaje najlepszą metodą iteracji przez aMap. ashishduh
@ karim79 co myślisz o następującym sposobie:Map<Integer, Integer> map = new HashMap<Integer, Integer>(); for (Map.Entry<Integer, Integer> entry : map.entrySet()) { System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); } fresh_dev
787

Jak iterować mapę w Javie:

Istnieje kilka sposobów iteracji po aMap w Javie. Przyjrzyjmy się najczęstszym metodom i przejrzyj ich zalety i wady. Ponieważ wszystkie mapy w Javie implementują interfejs Map, poniższe techniki będą działać przy każdej implementacji mapy (HashMap, TreeMap, LinkedHashMap, Hashtableitp.)

Metoda # 1: Iterowanie wpisów za pomocą pętli For-Each.

Jest to najczęściej stosowana metoda i jest preferowana w większości przypadków. Powinien być używany, jeśli potrzebujesz zarówno kluczy map, jak i wartości w pętli.

Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
    System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}

Zauważ, że pętla For-Each została wprowadzona w Javie 5, więc ta metoda działa tylko w nowszych wersjach języka. Rzuci także pętla For-EachNullPointerException jeśli spróbujesz iterować po mapie, która ma wartość null, więc przed iteracją zawsze powinieneś sprawdzać, czy nie ma pustych referencji.

Metoda # 2: Iterowanie nad kluczami lub wartościami za pomocą pętli For-Each.

Jeśli potrzebujesz tylko kluczy lub wartości z mapy, możesz iterować po parametrze keySet lub wartości zamiast entrySet.

Map<Integer, Integer> map = new HashMap<Integer, Integer>();

// Iterating over keys only
for (Integer key : map.keySet()) {
    System.out.println("Key = " + key);
}

// Iterating over values only
for (Integer value : map.values()) {
    System.out.println("Value = " + value);
}

Ta metoda daje niewielką przewagę nad wydajnościąentrySet iteracja (około 10% szybsza) i jest bardziej czysta.

Metoda # 3: Iterowanie za pomocą Iteratora.

Używanie generycznych:

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());
}

Bez generyków:

Map map = new HashMap();
Iterator entries = map.entrySet().iterator();
while (entries.hasNext()) {
    Map.Entry entry = (Map.Entry) entries.next();
    Integer key = (Integer)entry.getKey();
    Integer value = (Integer)entry.getValue();
    System.out.println("Key = " + key + ", Value = " + value);
}

Możesz również użyć tej samej techniki do iterowaniakeySet lub wartości.

Ta metoda może wyglądać na zbędną, ale ma swoje zalety. Przede wszystkim jest to jedyny sposób na iterację mapy w starszych wersjach Java. Inną ważną cechą jest to, że jest to jedyna metoda umożliwiająca usuwanie wpisów z mapy podczas iteracji przez wywołanieiterator.remove(). Jeśli spróbujesz to zrobić podczas iteracji For-Each, otrzymasz „nieprzewidywalne wyniki” zgodnie zJavadoc.

Z punktu widzenia wydajności ta metoda jest równa iteracji For-Each.

Metoda # 4: Iterowanie nad kluczami i wyszukiwanie wartości (nieefektywne).

Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Integer key : map.keySet()) {
    Integer value = map.get(key);
    System.out.println("Key = " + key + ", Value = " + value);
}

Może to wyglądać na czystszą alternatywę dla metody nr 1, ale w praktyce jest to dość powolne i nieefektywne, ponieważ uzyskanie wartości za pomocą klucza może być czasochłonne (ta metoda w różnych implementacjach map jest o 20% -200% wolniejsza niż metoda # 1 ). Jeśli masz zainstalowane FindBugs, wykryje to i ostrzeże Cię o nieefektywnej iteracji. Tej metody należy unikać.

Wniosek:

Jeśli potrzebujesz tylko kluczy lub wartości z mapy, użyj metody # 2. Jeśli utknąłeś ze starszą wersją Java (mniej niż 5) lub planujesz usunąć wpisy podczas iteracji, musisz użyć metody # 3. W przeciwnym razie użyj metody # 1.

@arvind W jaki sposób metoda 4 zawsze byłaby nieefektywna? Z definicji powołanieget() jest zawsze O (1) dla mapy HashMap. To jest definicja mapy HashMap, a użytkownik poprosił o HashMap. Nie rozumiem, dlaczego jest to tak wysoko wyartykułowane. Jeśli chcesz odwołać się do cudzego linku, upewnij się, że ma to sens dla zadanego pytania. ohbrobig
Dodajmy mały caevet, który w przypadkuConcurrentMaps, iteracja dalejkeySet() ulegnie awarii w ogóle (nie ma gwarancji, że istnieją wartości dla wcześniej zebranych kluczy). Z drugiej strony korzystanie z iteratorów lub wpisów jest bezpieczne (zawsze odnoszą się do istniejących obiektów). P Marecki
@ohbrobig jeszcze jest O (1), ale to jest środowisko wykonawcze, tak się skaluje. Nie oznacza to, że koniecznie otrzyma wartość w pierwszym cyklu. Metoda # 4 będzie zdecydowanie wolniejsza niż Metoda # 1 user961954
85

Możesz przeglądać wpisy w aMap na kilka sposobów. Uzyskaj każdy klucz i wartość w ten sposób:

Map<?,?> map = new HashMap<Object, Object>();
for(Entry<?, ?> e: map.entrySet()){
    System.out.println("Key " + e.getKey());
    System.out.println("Value " + e.getValue());
}

Możesz też uzyskać listę kluczy za pomocą

Collection<?> keys = map.keySet();
for(Object key: keys){
    System.out.println("Key " + key);
    System.out.println("Value " + map.get(key));
}

Jeśli chcesz uzyskać wszystkie wartości i nie interesują cię klucze, możesz użyć:

Collection<?> values = map.values();
43

że będziesz potrzebował zarówno klucza, jak i wartości każdego wpisu, przejdź przezentrySet. Jeśli potrzebujesz wartości, to jestvalues() metoda. A jeśli po prostu potrzebujesz kluczy, użyjkeyset().

Złą praktyką byłoby powtarzanie wszystkich kluczy, a następnie w pętli, zawszemap.get(key) aby uzyskać wartość. Jeśli to robisz, pierwszą opcją, którą napisałem, jest dla ciebie.

Jeszcze jeden ważny punkt: zestaw zwrócony przez keySet () i Collection zwrócony przez value () jest wspierany przez oryginalną Mapę. Oznacza to, że jeśli dokonasz w nich jakiejkolwiek modyfikacji, zostaną one odzwierciedlone na Mapie, jednak oba nie obsługują metod add () i addAll (), tj. Nie możesz dodać nowego klucza do Set lub nowej wartości w kolekcji. sactiw
60

Mądrzejszy:

for (String key : hashMap.keySet()) {
    System.out.println("Key: " + key + ", Value: " + map.get(key));
}
Składnia Java 8. Może nadal nie działać dla rozwoju Androida. „Android nie jest w 100% kompatybilny z żadną wersją Java SE API, nie 6 ani 8 ani żadną. ... JRE jest Java Runtime Environment, podczas gdy JDK jest Java Development Kit. To JDK, którego potrzebujesz do tworzenia aplikacji na Androida wraz z istniejącym Android SDK.Dec 9, 2013 ”źródło jasonleonhard
map.entrySet (), który zwraca wpisy, które już zawierają zarówno klucz, jak i wartość. W ten sposób nie musisz wywoływać hashCode () i przeszukiwać skrótu podczas iteracji. ComputerEngineer88
map.get (klucz) dla każdej iteracji nie jest mądrzejszy - na swój sposób wolniejszy ComputerEngineer88
to zależy od tego, czy potrzebujesz kluczy. jeśli nie, wydajniej jest użyć entrySet (), ponieważ hashCode () nie jest wywoływany. icfantv

Powiązane pytania