Java 8中的forEach循环用于Map条目集。

96

我正在尝试将旧版的传统for each循环转换成Java 8的Map entry set的for each循环,但是我遇到了错误。以下是我正在尝试转换的代码:

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)的签名不匹配。

8个回答

213
请阅读javadocMap<K, V>.forEach()方法需要一个BiConsumer<? super K,? super V>作为参数,而BiConsumer<T, U>抽象方法的签名是accept(T t, U u)

因此,您应该传递一个lambda表达式作为参数,该表达式接受两个输入参数:键和值:

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

如果您在地图的entry set上调用forEach(),您的代码将正常工作,而不是在地图本身上调用它:

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

好的。现在两种方式都可以工作。但哪一种更好?在哪种情况下性能会更好?@JBNizet - Siddharth Sachdeva
2
第二个版本需要为每个条目创建一个 Map.Entry 实例;而第一个版本可以直接给你键和值,无需实例化。因此,Map.Entry 是一个中间人,你可以使用第一个版本来避免它。 - Marko Topolnik
5
对于大多数 Map 实现,Map.Entry 实例在迭代之前已经存在,不需要创建。但是,在操作中不必处理 Map.Entry 可以提高可读性,并具有稍微更好的性能潜力,因为不需要调用额外的方法来检索键和值。 - Holger
2
@Holger,我会强调你的暗示:对于大多数但并非全部的Map实现来说是正确的,而ConcurrentHashMap则是一个重要的反例。 - Marko Topolnik
1
@Marko Topolnik:但是当迭代整个ConcurrentHashMap时,临时条目实例是最不用担心的事情。尽管如此,我们仍然同意更喜欢使用map.forEach((key, value) -> …);... - Holger

16
也许回答类似“哪个版本更快,我应该使用哪个版本?”的问题最好的方法是查看源代码: 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.entrySet().forEach() 的情况下获得任何性能优势。所以在你的情况下,答案真的取决于你个人的喜好 :)

有关差异的完整列表,请参阅提供的 javadoc 链接。愉快编码!


6
您可以使用以下代码满足您的要求。
map.forEach((k,v)->System.out.println("Item : " + k + " Count : " + v));

4
这个答案与JB Nizet 2年前提供的答案的一部分完全相同,没有提供任何额外有用的信息。 - Madbreaks

2

以下是三种最好的方法来实现它: 1. 使用 entry set 进行迭代

for (Map.Entry<String, Integer> entry : map.entrySet()) {
    System.out.println(entry.getKey() + ":" + entry.getValue());
}
  1. Lambda表达式 map.forEach((k, v) -> System.out.println((k + ":" + v)));

3 流式操作 map.entrySet().stream() .forEach(e -> System.out.println(e.getKey() + ":" + e.getValue()));


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

虽然这段代码片段可能是解决方案,但包括解释真的有助于提高您的帖子质量。请记住,您正在回答未来读者的问题,而这些人可能不知道您的代码建议的原因。 - Neo Anderson

0

流 API

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

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

请在您的答案中添加一些解释。这将有助于其他人根据自己的需求进行调整。[来自审查] (https://stackoverflow.com/review/low-quality-posts/22357648)。 - Wai Ha Lee

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

result.put(1, "Motorbike");
result.put(2, "Car");
result.put(3, "Jeep");

result.forEach((key,value)->System.out.println(key+ "  "+value));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接