JDK-8016431 : Default implementation of Map.replaceAll fails for CSLM
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util:collections
  • Priority: P3
  • Status: Resolved
  • Resolution: Duplicate
  • Submitted: 2013-06-11
  • Updated: 2021-03-03
  • Resolved: 2013-09-30
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8
8Resolved
Related Reports
Relates :  
Description
The default implementation of Map.replaceAll:

    default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
        Objects.requireNonNull(function);
        for (Map.Entry<K, V> entry : entrySet()) {
            K k;
            V v;
            try {
                k = entry.getKey();
                v = entry.getValue();
            } catch(IllegalStateException ise) {
                throw new ConcurrentModificationException(ise);
            }
            entry.setValue(function.apply(k, v));
        }
    }

fails with UOE on ConcurrentSkipListMap because its entrySet returns immutable map entries.  The default should instead do:

    map.put(k, apply(k, v))

As part of a separate issue, HashMap, TreeMap, LinkedHashMap, ConcurrentHashMap, and ConcurrentSkipListMap should consider overridding Map.replaceAll, because the default is likely to be not as performant.  
Comments
Resolved in JDK-8016446
30-09-2013

The following implementation was added to CSLM as part of another changeset, see http://hg.openjdk.java.net/jdk8/tl/jdk/rev/dfd7fb0ce54b public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { if (function == null) throw new NullPointerException(); V v; for (Node<K,V> n = findFirst(); n != null; n = n.next) { while ((v = n.getValidValue()) != null) { V r = function.apply(n.key, v); if (r == null) throw new NullPointerException(); if (n.casValue(v, r)) break; } } }
28-08-2013

I have added a better default in ConcurrentMap
12-07-2013

Doug has prposed adding an override to ConcurrentMap.
25-06-2013

I would prefer to just add the necessary override to CSLM. The setValue approach is the most general and usually offers better performance and safety than combining iteration and put.
12-06-2013