forEach循环Java 8 for Map条目集

Sid*_*eva 72 java lambda java-8

我正在尝试将每个循环的旧常规转换为java7到java8的每个循环用于映射条目集但是我收到错误.这是我要转换的代码:

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

这是我所做的改变:

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

   }); 
Run Code Online (Sandbox Code Playgroud)

我也尝试过这样做:

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

   });
Run Code Online (Sandbox Code Playgroud)

但仍面临错误.我得到的错误是:Lambda表达式的签名与功能接口方法的签名不匹配accept(String, String)

JB *_*zet 173

读取javadoc:Map<K, V>.forEach()期望一个BiConsumer<? super K,? super V>as参数,并且BiConsumer<T, U>抽象方法的签名是accept(T t, U u).

所以你应该传递一个lambda表达式,它接受两个输入作为参数:键和值:

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

如果您在地图的条目集上调用forEach()而不在地图本身上,则您的代码将起作用:

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

  • @Marko Topolnik:对于大多数`Map`实现,`Map.Entry`实例在迭代之前已经存在,不需要创建.尽管如此,在操作中不必处理`Map.Entry`是可读性的胜利,并且具有更好的性能,因为不需要额外的方法调用来检索密钥和值. (4认同)
  • 第二个版本强制为每个条目创建一个`Map.Entry`实例; 第一个为您提供密钥和值,没有实例化.因此`Map.Entry`是一个中间人,您可以使用第一个版本来避免它. (2认同)
  • @Holger我会强调你的隐含意义:对于大多数人来说,_但不是all_,`Map`实现是真的,`ConcurrentHashMap`是一个重要的反例. (2认同)

Evg*_*rev 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

的javadoc

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

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

的javadoc

这立即显示map.forEach()也在内部使用Map.Entry.因此,我不希望在map.entrySet().forEach()上使用map.forEach()有任何性能优势.所以在你的情况下答案真的取决于你的个人品味:)

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


小智 6

您可以根据需要使用以下代码

map.forEach((k,v)->System.out.println("Item : " + k + " Count : " + v));
Run Code Online (Sandbox Code Playgroud)

  • 这个答案与 JB Nizet 2 年前提供的答案的_部分相同,并且没有提供额外的有用信息。 (2认同)