2015-08-28 16 views
40

Próbuję konwertować stary konwencjonalny dla każdej pętli, aż do java7 do java8 dla każdej pętli dla zestawu pozycji mapy, ale dostaję błąd. Oto kod próbuję przekonwertować:forEach pętla Java 8 dla zestawu wpisów mapy

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

Oto zmiany zrobiłem:

map.forEach(Map.Entry<String, String> entry -> { 
     System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue()); 

    }); 

Próbowałem robić to za dobrze:

Map.Entry<String, String> entry; 
    map.forEach(entry -> { 
     System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue()); 

    }); 

Ale nadal napotyka błąd . Błąd Dostaję za to: podpis Lambda Expression nie pasuje podpis funkcjonalnej metody interfejsu accept(String, String)

Odpowiedz

103

Czytaj the javadoc: Map<K, V>.forEach() oczekuje BiConsumer<? super K,? super V> jako argument i podpis BiConsumer<T, U> abstrakcyjnej metody jest accept(T t, U u).

Więc należy przekazać go do wyrażenia lambda, które ma dwa wejścia jako argumentu: klucz i wartość:

map.forEach((key, value) -> { 
    System.out.println("Key : " + key + " Value : " + value); 
}); 

Twój kod będzie działać, jeśli nazywa foreach() na zbiorze wejściowym mapie nie na samej mapie:

map.entrySet().forEach(entry -> { 
    System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue()); 
}); 
+0

Wielki. Teraz działa oba. Ale który z nich jest lepszy? W takim przypadku wydajność byłaby lepsza? @JBNizet –

+2

Druga wersja wymusza utworzenie instancji 'Map.Entry' dla każdego wpisu; pierwszy daje ci klucz i wartość bez instancji. Dlatego 'Map.Entry' jest pośrednikiem i możesz tego uniknąć używając pierwszej wersji. –

+0

Dzięki @MarkoTopolnik Dostałem twój punkt. –

8

Być może najlepszym sposobem, aby odpowiedzieć na pytania typu "która wersja jest szybsza i który powinienem użyć?" jest spojrzenie do kodu źródłowego.

map.forEach() - od Map.java

default void forEach(BiConsumer<? super K, ? super V> action) { 
    Objects.requireNonNull(action); 
    for (Map.Entry<K, V> entry : entrySet()) { 
     K k; 
     V v; 
     try { 
      k = entry.getKey(); 
      v = entry.getValue(); 
     } catch(IllegalStateException ise) { 
      // this usually means the entry is no longer in the map. 
      throw new ConcurrentModificationException(ise); 
     } 
     action.accept(k, v); 
    } 
} 

javadoc

map.entrySet() foreach() - od iterowalny .java

default void forEach(Consumer<? super T> action) { 
    Objects.requireNonNull(action); 
    for (T t : this) { 
     action.accept(t); 
    } 
} 

javadoc

To natychmiast ujawnia, że ​​map.forEach() używa również wewnętrznie Map.Entry. Tak więc nie spodziewałbym się żadnych korzyści związanych z wydajnością korzystania z map.forEach() przez map.entrySet(). ForEach(). Tak więc w twoim przypadku odpowiedź naprawdę zależy od Twojego gustu :)

Pełna lista różnic znajduje się w dostarczonych linkach javadoc. Szczęśliwe kodowanie!

4

Można użyć następującego kodu do wymogu

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