forEachループJava8 forMapエントリセット


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

   });

しかし、まだエラーに直面しています。これで発生するエラーは次のとおりです。Lambda式のシグネチャが関数型インターフェイスメソッドのシグネチャと一致しませんaccept(String, String)

回答:


193

javadocを読んでください:引数としてMap<K, V>.forEach()aBiConsumer<? super K,? super V>を期待し、BiConsumer<T, U>抽象メソッドのシグネチャはaccept(T t, U u)です。

したがって、引数として2つの入力(キーと値)を受け取るラムダ式を渡す必要があります。

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
Siddharth Sachdeva 2015

2
2番目のバージョンでMap.Entryは、エントリごとにインスタンスが強制的に作成されます。最初のものは、インスタンス化なしでキーと値を提供します。したがってMap.Entry、仲介者であり、最初のバージョンを使用してそれを回避できます。
Marko Topolnik 2015

5
@Marko Topolnik:ほとんどのMap実装では、Map.Entryインスタンスは反復前にすでに存在しているため、作成する必要はありません。それでも、Map.Entryアクションで対処する必要がないことは読みやすさのメリットであり、キーと値を取得するために追加のメソッド呼び出しが必要ないため、パフォーマンスが向上する可能性がわずかにあります。
ホルガー

2
@Holger私はあなたの暗黙の含意を強調します:すべてはありませんが、ほとんどのMap場合、それは真実でConcurrentHashMapあり、重要な反例です。
Marko Topolnik 2015

1
@Marko Topolnik:しかし、全体を反復処理する場合ConcurrentHashMap、一時的なエントリインスタンスが最後に心配する必要があります。それにもかかわらず、私たちはmap.forEach((key, value) -> …);とにかく好むことに同意します…
Holger

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
この回答は、2年前にJB Nizetによって提供された回答の一部と同一であり、追加の有用な情報を提供していません。
マッドブレイク2018

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

このコードスニペットが解決策かもしれませんが、説明を含めると、投稿の品質を向上させるのに役立ちます。あなたは将来読者のために質問に答えていることを忘れないでください、そしてそれらの人々はあなたのコード提案の理由を知らないかもしれません。
ネオアンダーソン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.