On Mon, 23 Feb 2026 14:44:59 GMT, Oli Gillespie <[email protected]> wrote:
>> Oh I understand now. The default Set spliterator is `Spliterator<T>
>> spliterator(Collection<? extends T> c, int characteristics)`. It doesn't
>> create an iterator until forEachRemaining is called, which in the test is
>> *after* the .remove modification, so it doesn't observe a discrepancy. The
>> new implementation uses creates the iterator up-front to pass to
>> `spliteratorUnknownSize`, so in that case the iterator is created before the
>> modification, hence CME.
>
> It ends up something like this:
>
>
> public static void main(String[] args) {
> List<String> strings = new LinkedList<>();
> strings.add("foo");
> strings.add("bar");
>
> Spliterator<String> s = Spliterators.spliterator(strings,
> Spliterator.DISTINCT); // Don't create iterator yet
> strings.remove(strings.iterator().next());
> s.forEachRemaining(System.out::println); // Spliterator creates iterator
> here, after the .remove call. No CME
>
> s = Spliterators.spliteratorUnknownSize(strings.iterator(),
> Spliterator.DISTINCT); // Eagerly create the iterator
> strings.remove(strings.iterator().next()); // Modifying after the
> iterator was created
> s.forEachRemaining(System.out::println); //
> ConcurrentModificationException
> }
>
>
> So it's just a side effect of `spliteratorUnknownSize` needing the iterator
> to be created already. I think the test skip is valid, then - it's true that
> this case is no longer lazy like it was.
Yes, seems you cannot create a spliterator with a lazy iterator. This is fine.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/28608#discussion_r2841502408