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

Reply via email to