forEach循环Java 8 for Map条目集


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)

Answers:


191

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

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

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

2
第二个版本强制Map.Entry为每个条目创建一个实例。第一个给您键和值而无需实例化。因此Map.Entry是一个中间人,您可以避免使用第一个版本。
Marko Topolnik

5
@Marko Topolnik:对于大多数Map实现而言,Map.Entry实例在迭代之前就已经存在,无需创建。尽管如此,不必Map.Entry在操作中进行处理就可以提高可读性,并且具有较小的潜力可以提高性能,因为不需要其他方法调用即可检索键和值。
Holger

2
@Holger我会强调你的默契含义:对于大多数,但不是全部Map实现这是真的,ConcurrentHashMap作为一个重要的反例。
Marko Topolnik

1
@Marko Topolnik:但是当遍历整个ConcurrentHashMap实例时,临时入口实例是最后要担心的事情。然而,无论如何,我们同意偏爱map.forEach((key, value) -> …);……
Holger 2015年

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

Java文档

map.entrySet()。forEach() -来自Iterable.java

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

Java文档

这立即表明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提供的答案的一部分相同,并且未提供其他有用的信息。
Madbreaks'Sep

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

尽管此代码段可能是解决方案,但包括说明确实有助于提高帖子的质量。请记住,您将来会为读者回答这个问题,而这些人可能不知道您提出代码建议的原因。
Neo Anderson
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.