ConcurrentHashMap中的forEach和forEachEntry有什么区别

Bon*_*ond 5 java java-8

在 Java 8 中ConcurrentHashMap引入了两个新方法,即。forEachforEachEntry

他们两个细看有基本相同的参数-forEach已通过提供的密钥值BiConsumer,同时forEachEntryMap.Entry通过提供Consumer从那里键和值可以得到。

打印所有地图条目的简单用例可以由它们中的任何一个实现,如下所示

ConcurrentHashMap<String, Integer> map = Stream.of("One", "Two", "Three", "Four", "Five").
            collect(Collectors.toConcurrentMap( str -> str, 
                                                str -> str.length(), 
                                                (str, len) -> len, 
                                                ConcurrentHashMap::new));

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

map.forEachEntry(1, entry -> System.out.println(entry.getKey() + " " + entry.getValue()));
Run Code Online (Sandbox Code Playgroud)

此外,文档Map.Entry.setValue不支持批量操作;所以拥有Map.Entry过于简单的键值的好处似乎被打败了。

.... 在计算过程中可能会暂时改变;除了 forEach 操作,理想情况下应该是无副作用的。Map.Entry对象上的批量操作支持 method setValue

因此 IMO 两种方法可以互换使用(除非我错过了一些非常明显的东西

所以我的问题是

  • 为什么引入了两种签名基本相同的方法
  • 如果有任何差异,它们是什么
  • 一种方法比另一种方法有什么好处(一个简单的用例解释它们就足够了

use*_*421 4

唯一的区别是,一个接受 BiConsumer,另一个只接受 Consumer。

这里是相关代码:

// forEach
static final class ForEachMappingTask<K,V>
    extends BulkTask<K,V,Void> {
    final BiConsumer<? super K, ? super V> action;
    ForEachMappingTask
        (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
         BiConsumer<? super K,? super V> action) {
        super(p, b, i, f, t);
        this.action = action;
    }
    public final void compute() {
        final BiConsumer<? super K, ? super V> action;
        if ((action = this.action) != null) {
            for (int i = baseIndex, f, h; batch > 0 &&
                     (h = ((f = baseLimit) + i) >>> 1) > i;) {
                addToPendingCount(1);
                new ForEachMappingTask<K,V>
                    (this, batch >>>= 1, baseLimit = h, f, tab,
                     action).fork();
            }
            for (Node<K,V> p; (p = advance()) != null; )
                action.accept(p.key, p.val);
            propagateCompletion();
        }
    }
}

// forEachEntry
static final class ForEachEntryTask<K,V>
    extends BulkTask<K,V,Void> {
    final Consumer<? super Entry<K,V>> action;
    ForEachEntryTask
        (BulkTask<K,V,?> p, int b, int i, int f, Node<K,V>[] t,
         Consumer<? super Entry<K,V>> action) {
        super(p, b, i, f, t);
        this.action = action;
    }
    public final void compute() {
        final Consumer<? super Entry<K,V>> action;
        if ((action = this.action) != null) {
            for (int i = baseIndex, f, h; batch > 0 &&
                     (h = ((f = baseLimit) + i) >>> 1) > i;) {
                addToPendingCount(1);
                new ForEachEntryTask<K,V>
                    (this, batch >>>= 1, baseLimit = h, f, tab,
                     action).fork();
            }
            for (Node<K,V> p; (p = advance()) != null; )
                action.accept(p);
            propagateCompletion();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

不知何故,有两种设置组件大小的方法:setSize(Dimension)setSize(int, int)