RFR: 8372946 - TreeMap sub-map entry spliterator is expensive [v4]

Chen Liang liach at openjdk.org
Mon Feb 23 15:35:40 UTC 2026


On Mon, 23 Feb 2026 14:44:59 GMT, Oli Gillespie <ogillespie at openjdk.org> 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


More information about the core-libs-dev mailing list