On Mon, 23 Feb 2026 14:17:53 GMT, Oli Gillespie <[email protected]> wrote:

>> test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/CollectionAndMapModifyStreamTest.java
>>  line 123:
>> 
>>> 121: 
>>> 122:         // The following are not lazy
>>> 123: //        maps.put(TreeMap.class.getName() + ".descendingMap()", () -> 
>>> new TreeMap<>(content).descendingMap());
>> 
>> Is this test modification still necessary?
>
> That case still fails, yes, but I'm not totally sure why. I'm looking into it.
> 
> 
> java.util.ConcurrentModificationException
>       at 
> java.base/java.util.TreeMap$NavigableSubMap$SubMapIterator.prevEntry(TreeMap.java:2070)
>       at 
> java.base/java.util.TreeMap$NavigableSubMap$DescendingSubMapEntryIterator.next(TreeMap.java:2121)
>       at 
> java.base/java.util.TreeMap$NavigableSubMap$DescendingSubMapEntryIterator.next(TreeMap.java:2114)
>       at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
>       at 
> java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1939)
>       at 
> java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:570)
>       at 
> java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:560)
>       at 
> java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:635)
>       at 
> java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:291)
>       at 
> java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:652)
>       at 
> java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:658)
>       at 
> org.openjdk.tests.java.util.stream.CollectionAndMapModifyStreamTest.testEntrySetSizeRemove(CollectionAndMapModifyStreamTest.java:164)
>       at 
> org.openjdk.tests.java.util.stream.CollectionAndMapModifyStreamTest.testMapEntriesSizeRemove(CollectionAndMapModifyStreamTest.java:155)

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.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/28608#discussion_r2841224287

Reply via email to