dl at cs.oswego.edu
Thu Oct 6 07:30:00 EDT 2011
On 10/05/11 18:31, David M. Lloyd wrote:
>> In the case of ConcurrentHashMap, this means that the
>> kind of Entry you get for the elements of entrySet.toArray
>> should NOT write back to the map you got them from.
>> In other words:
>> Object a = myMap.entrySet().toArray();
>> should not change myMap.get(keyFor0) to return 17.
> I disagree with this conclusion; these scenarios aren't really the same. The
> general contract of toArray() is to return an array consisting of all the values
> in the collection - I think interpreting it such that it can return copies of
> the values is a stretch. I can't think of any case where we'd actually copy the
> values in normal collections;
Never deep copies. But always shallow copies. For example
Object a = myMap.values().toArray();
a = 17;
also does not change myMap.get(keyFor0) to return 17 in
any JDK Map implementation.
Besides not wanting to set up side-channels for modifications,
the various toArray methods must have snapshot-like semantics
because they cannot possibly track additions and removals
occurring after (or concurrently with) the array creation.
This is the basis for the the lifetime disclaimers in the
Several people seem to have the feeling that entrySet().toArray()
should be somehow different about these policies because they know
that HashMap in particular returns internal mutable Entry objects.
Which is arguably also a bad idea. But most other Maps do not
do this. They instead return distinct Entry objects
that snapshot current mappings while usually still supporting
setValue for one-by-one traversal in the same way that CHM does,
invoking map.put. Which is a little bit crazy -- we add some
time/space overhead to entrySet operations just to imperfectly
reinforce the questionable intuition that methods operate
directly on internal Entry objects that don't actually exist
(and need not actually exist wrt any other aspects of Map specs).
More information about the Concurrency-interest