Is a peculiar structural modification permissible while iterating a List using the fail-fast iterator?

Martin Buchholz martinrb at google.com
Sat Mar 24 18:42:27 UTC 2018


https://docs.oracle.com/javase/9/docs/api/java/util/ConcurrentModificationException.html


On Sat, Mar 24, 2018 at 11:13 AM, kedar mhaswade <kedar.mhaswade at gmail.com>
wrote:

> I apologize in advance if this has been asked before or if I am making a
> rookie mistake.
>
> Consider the program [1]. In Josh Bloch and Neal Gafter style (I miss those
> Puzzlers at JavaOnes), may I ask, "What does this program print?"
>
> As some of you may have guessed correctly, this program works *as naively
> expected* in that it (erroneously) removes the desired stooge from stooges
> and prints the list of remaining ones. Some analysis of the fail-fast
> iterator code in java.util.AbstractList$Itr and java.util.ArrayList$Itr
> suggests that only the item that is at the penultimate index in the backing
> list could be removed this way (i.e. *without* the fail-fast iterator
> detecting its structural modification). This appears to be because the
> implementation of hasNext() only checks if the cursor is equal to size
> without ensuring whether the expected and actual modification counts agree.
> My confusion is whether this is specified somewhere. None of
> java.util.Iterator#hasNext and java.util.ListIterator#hasNext seem to
> provide any specification about this. And hence it is not clear whether or
> not the hasNext() implementation must detect this peculiar structural
> modification. It is *not *specified if hasNext() may not throw
> ConcurrentModificationException. An unfortunate consequence is that an
> oversight on programmer's part (List#remove() instead of Iterator#remove)
> seems to go undetected.
>
> Is this a bug, or a feature?
>
> Regards,
> Kedar
>
> PS - It's entirely possible that I am not reading the code fully. I am
> checked the JDK 1.8.0_131 and Open JDK 1.9.0_181 sources.
>
>
> [1]
>
> import java.util.ArrayList;import java.util.List;import static
> java.util.Arrays.asList;public class ExceptionallyNamedException {
> public static void main(String[] args) {        List<String> stooges =
> new ArrayList<>(asList("Larry", "Moe", "Curly", "Jo", "Blo"));
> for (String stooge : stooges) {            if ("Jo".equals(stooge)) {
> *// no other stooge may be removed erroneously
> *                stooges.remove(stooge); *// erroneous removal, use
> iterator!
> *            }        }
>         System.out.println(stooges);    }
> }
>


More information about the core-libs-dev mailing list