RFR : 8016446 : (m) Add override forEach/replaceAll to HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap

Paul Sandoz paul.sandoz at oracle.com
Fri Jun 14 10:55:38 UTC 2013


On Jun 14, 2013, at 12:12 PM, Remi Forax <forax at univ-mlv.fr> wrote:
>> 
>> The following does not throw CME:
>> 
>>             List<Integer> l = new ArrayList<>(Arrays.asList(1, 2));
>>             for (Integer i : l) {
>>                 l.remove(1);  // 2 is never encountered
>>             }
>> 
>> Where as the following does:
>> 
>>             List<Integer> l = new ArrayList<>(Arrays.asList(1, 2, 3));
>>             for (Integer i : l) {
>>                 l.remove(1);
>>             }
>> 
>> Because the hasNext implementation does not check for modification. It's sad this also occurs for the default implementation of Iterable.forEach :-(
>> 
>> This behaviour sucks.
> 
> devil advocate: why exactly, the iteration is finished when you remove the element ?

The latter because a CME is thrown; the former because hasNext returns false.

The above is an example of how a bug can be hidden depending on the state (# elements) of the collection.


> 
>> It would be a shame for overriding forEach/forEachRemaining implementations to conform to such behaviour when they can implement stronger/consistent failure guarantees.
> 
> While I could agree with you in theory, in practice I have seen several times codes that rely on this behaviour,
> usually there is a bunch of method calls between the for loop and the list.remove() so this is not something that can be easily fixed.

A bug none the less, yes?


> And because I think it's more important that users should be able to use either for(:) or forEach without thinking too much,
> because otherwise nodoby will "modernize" their code, we have no choice but stick to the iterator behaviour for forEach
> i.e. no modCount check at the end.
> 

So you argument is based on the the premise that existing buggy code should continue work?

Paul.


More information about the core-libs-dev mailing list