-
Bug
-
Resolution: Fixed
-
P4
-
7
-
generic
-
generic
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.
--------
(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.