JDK-7006877 : (alt-rt coll) TreeMap set view of mappings doesn't support setValue
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util:collections
  • Affected Version: 7
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2010-12-14
  • Updated: 2013-09-20
  • Resolved: 2013-09-20
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
8Fixed
Description
SYNOPSIS
--------
(alt-rt) TreeMap set view of mappings doesn't support setValue
-or-
Experimental TreeMap implementation does not allow modification via Iterator

OPERATING SYSTEMS
-----------------
All

FULL JDK VERSION
----------------
1.6.0_14 onwards, with -XX:+AggressiveOpts enabled

PROBLEM DESCRIPTION from LICENSEE
---------------------------------
An experimental implementation of TreeMap was added in 1.6.0_14:

http://www.oracle.com/technetwork/java/javase/6u14-137039.html#performance-6u14

This new implementation is enabled via the command line option -XX:+AggressiveOpts.

With the standard TreeMap implementation, the value of Map.Entry key/value pairs returned by TreeMap's Iterator can be modified by calling Map.Entry.setValue().

With the experimental implemention enabled, it is not possible to modify the values in this way. Calls to Map.Entry.setValue() result in an UnsupportedOperationException. This seems to be because the experimental implementation returns an immutable Entry (defined in AbstractMap) - so this behaviour seems to be intentional. However, since the default TreeMap implementation's Iterator returns mutable Map.Entry objects, the change in the experimental TreeMap breaks backward compatibility.

The situation is made more confusing by the API documentation for TreeMap. The documentation was changed in Java 6, with the addition of the following paragraph:

"All Map.Entry pairs returned by methods in this class and its views
represent snapshots of mappings at the time they were produced. They do
not support the Entry.setValue method. (Note however that it is
possible to change mappings in the associated map using put.)"

http://download.oracle.com/javase/6/docs/api/java/util/TreeMap.html

This would represent a significant change in behaviour vs 5.0 - it would would break backwards compatibility, and it is debatable whether a small addition to the API documentation is sufficient to cover/explain it. In addition, the provided testcase demonstrates that it is not even correct - Map.Entry pairs returned by the default TreeMap implementation's Iterator DO support the Entry.setValue method.

It is also worth noting that the documentation for TreeMap.entrySet(), which returns the Iterator, states the following:

"Returns a Set view of the mappings contained in this map. The set's
 iterator returns the entries in ascending key order. The set is backed
 by the map, so changes to the map are reflected in the set, and
 vice-versa. If the map is modified while an iteration over the set is
 in progress (except through the iterator's own remove operation, or
 through the setValue operation on a map entry returned by the iterator)
 the results of the iteration are undefined."

 http://download.oracle.com/javase/6/docs/api/java/util/TreeMap.html#entrySet%28%29

Which would suggest that setValue() IS supported, contrary to the new paragraph at the beginning of the TreeMap documentation.

So, in summary, it's not clear whether this is a bug in the experimental TreeMap implementation, a bug in the default TreeMap implementation, or a documentation bug. This report is being filed to obtain a definitive answer on this subject.

TESTCASE
--------
import java.util.*;

public class TreeMapTest {
    public static void main(String[] args) {     
        TreeMap<String,Integer> map = new TreeMap<String,Integer>();             
        map.put("A", 1);           
        Iterator iter = map.entrySet().iterator();
        Map.Entry entry = (Map.Entry)iter.next();
        entry.setValue(new Integer(2));       
    }                                           
} 

REPRODUCTION INSTRUCTIONS
-------------------------
1. javac TreeMapTest.java
2. java -XX:+AggressiveOpts TreeMapTest

Example output:

Exception in thread "main" java.lang.UnsupportedOperationException
        at java.util.AbstractMap$SimpleImmutableEntry.setValue(AbstractMap.java:726)
        at TreeMapTest.main(TreeMapTest.java:10)

WORKAROUND
----------
See Workaround section.

Comments
resolved via JDK-8024826
20-09-2013

alt-rt implementation will be removed
10-09-2013

WORK AROUND Workaround submitted by IBM: -- Don't run with -XX:+AggressiveOpts, or remove/rename [JAVA HOME]/jre/lib/alt-rt.jar to disable the experimental TreeMap implementation. --
14-12-2010