forEach цикл Java 8 для набору введення карти


82

Я намагаюся перетворити старий звичайний для кожного циклу до java7 в java8 для кожного циклу для набору введення карти, але я отримую помилку. Ось код, який я намагаюся конвертувати:

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

Ось зміни, які я вніс:

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

   }); 

Я спробував зробити це також:

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

   });

Але все одно стикається з помилкою. Помилка, яку я отримую за це, полягає в тому, що підпис лямбда-виразу не відповідає підпису методу функціонального інтерфейсуaccept(String, String)

Відповіді:


193

Прочитайте javadoc : Map<K, V>.forEach()очікує BiConsumer<? super K,? super V>як аргумент, а підпис BiConsumer<T, U>абстрактного методу - accept(T t, U u).

Отже, ви повинні передати йому лямбда-вираз, який бере два аргументи як аргумент: ключ і значення:

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

Ваш код працював би, якщо ви закликали forEach () у наборі введення карти, а не на самій карті:

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

Чудово. Зараз працюють обидва. Але який із них кращий спосіб? В якому випадку продуктивність була б кращою? @JBNizet
Сіддхарт

2
Друга версія примушує створювати Map.Entryекземпляр для кожного запису; перший дає вам ключ і значення без екземпляра. Тому Map.Entryпосередник, і ви можете уникнути цього, використовуючи першу версію.
Марко Топольник

5
@Marko Topolnik: для більшості Mapреалізацій Map.Entryекземпляри вже існують до ітерації і їх не потрібно створювати. Тим не менше, відсутність необхідності мати справу з Map.Entryдією - це виграш у читабельності та невеликий потенціал для кращої роботи, оскільки для отримання ключа та значення не потрібні додаткові виклики методів.
Holger

2
@Holger Я наголошу на вашому мовчазному натяку: для більшості, але не для всіх , Mapреалізації, які відповідають дійсності, ConcurrentHashMapє важливим контраприкладом.
Марко Топольник

1
@Marko Topolnik: але при ітерації протягом цілого ConcurrentHashMap, екземпляри тимчасового входу - це останнє, про що слід турбуватися. Тим не менше, ми погоджуємось на map.forEach((key, value) -> …);все-таки віддавати перевагу ...
Холгер

13

Можливо, найкращий спосіб відповісти на запитання типу "яка версія швидша, а яку використовувати?" полягає у зверненні до вихідного коду:

map.forEach () - з 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 () - з Iterable.java

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

javadoc

Це негайно виявляє, що map.forEach () також використовує Map.Entry внутрішньо. Тому я б не очікував жодної вигоди від продуктивності використання map.forEach () над map.entrySet (). ForEach () . Тож у вашому випадку відповідь справді залежить від вашого особистого смаку :)

Повний перелік відмінностей див. У наданих посиланнях javadoc. Щасливого кодування!


7

Ви можете використовувати наступний код для своїх вимог

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

2
Ця відповідь ідентична частині відповіді, наданої JB Nizet 2 роки тому, і не містить додаткової корисної інформації.
Madbreaks

0
HashMap<String,Integer> hm = new HashMap();

 hm.put("A",1);
 hm.put("B",2);
 hm.put("C",3);
 hm.put("D",4);

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

Будь ласка, додайте пояснення до своєї відповіді. Це допоможе іншим адаптувати вашу відповідь до власних потреб. З огляду .
Вай Ха Лі

0

API потоку

public void iterateStreamAPI(Map<String, Integer> map) {
    map.entrySet().stream().forEach(e -> System.out.println(e.getKey() + ":"e.getValue()));
}

0
String ss = "Pawan kavita kiyansh Patidar Patidar";
    StringBuilder ress = new StringBuilder();
    
    Map<Character, Integer> fre = ss.chars().boxed()
            .collect(Collectors.toMap(k->Character.valueOf((char) k.intValue()),k->1,Integer::sum));
    
      //fre.forEach((k, v) -> System.out.println((k + ":" + v)));
    
    fre.entrySet().forEach(e ->{
            //System.out.println(e.getKey() + ":" + e.getValue());
            //ress.append(String.valueOf(e.getKey())+e.getValue());
        }); 

    fre.forEach((k,v)->{
        //System.out.println("Item : " + k + " Count : " + v);
        ress.append(String.valueOf(k)+String.valueOf(v));
    });
    
    System.out.println(ress.toString());

Хоча цей фрагмент коду може бути рішенням, включаючи пояснення, він дійсно допомагає поліпшити якість вашої публікації. Пам’ятайте, що ви будете відповідати на запитання для читачів у майбутньому, і ці люди можуть не знати причин вашої пропозиції коду.
Нео Андерсон,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.