diff --git a/src/java.base/share/classes/java/util/stream/SortedOps.java b/src/java.base/share/classes/java/util/stream/SortedOps.java index 91892eba44f..1286735ebd9 100644 --- a/src/java.base/share/classes/java/util/stream/SortedOps.java +++ b/src/java.base/share/classes/java/util/stream/SortedOps.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -108,13 +108,10 @@ final class SortedOps { * {@code Comparable}. */ OfRef(AbstractPipeline upstream) { - super(upstream, StreamShape.REFERENCE, - StreamOpFlag.IS_ORDERED | StreamOpFlag.IS_SORTED); - this.isNaturalSort = true; // Will throw CCE when we try to sort if T is not Comparable @SuppressWarnings("unchecked") Comparator comp = (Comparator) Comparator.naturalOrder(); - this.comparator = comp; + this(upstream, comp); } /** @@ -123,10 +120,13 @@ final class SortedOps { * @param comparator The comparator to be used to evaluate ordering. */ OfRef(AbstractPipeline upstream, Comparator comparator) { + Objects.requireNonNull(comparator); + boolean isNaturalSort = Comparator.naturalOrder().equals(comparator); + this.comparator = comparator; + this.isNaturalSort = isNaturalSort; super(upstream, StreamShape.REFERENCE, - StreamOpFlag.IS_ORDERED | StreamOpFlag.NOT_SORTED); - this.isNaturalSort = false; - this.comparator = Objects.requireNonNull(comparator); + StreamOpFlag.IS_ORDERED | + (isNaturalSort ? StreamOpFlag.IS_SORTED : StreamOpFlag.NOT_SORTED)); } @Override diff --git a/src/java.base/share/classes/java/util/stream/StreamOpFlag.java b/src/java.base/share/classes/java/util/stream/StreamOpFlag.java index df98125cbc0..0e7b2f6607b 100644 --- a/src/java.base/share/classes/java/util/stream/StreamOpFlag.java +++ b/src/java.base/share/classes/java/util/stream/StreamOpFlag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ */ package java.util.stream; +import java.util.Comparator; import java.util.EnumMap; import java.util.Map; import java.util.Spliterator; @@ -738,9 +739,9 @@ enum StreamOpFlag { * * @implSpec * If the spliterator is naturally {@code SORTED} (the associated - * {@code Comparator} is {@code null}) then the characteristic is converted - * to the {@link #SORTED} flag, otherwise the characteristic is not - * converted. + * {@code Comparator} is {@code null} or {@code Comparator.naturalOrder()}) then + * the characteristic is converted to the {@link #SORTED} flag, otherwise + * the characteristic is not converted. * * @param spliterator the spliterator from which to obtain characteristic * bit set. @@ -748,14 +749,15 @@ enum StreamOpFlag { */ static int fromCharacteristics(Spliterator spliterator) { int characteristics = spliterator.characteristics(); - if ((characteristics & Spliterator.SORTED) != 0 && spliterator.getComparator() != null) { - // Do not propagate the SORTED characteristic if it does not correspond - // to a natural sort order - return characteristics & SPLITERATOR_CHARACTERISTICS_MASK & ~Spliterator.SORTED; - } - else { - return characteristics & SPLITERATOR_CHARACTERISTICS_MASK; + if ((characteristics & Spliterator.SORTED) != 0) { + Comparator comparator = spliterator.getComparator(); + if (comparator != null && !Comparator.naturalOrder().equals(comparator)) { + // Do not propagate the SORTED characteristic if it does not correspond + // to a natural sort order + return characteristics & SPLITERATOR_CHARACTERISTICS_MASK & ~Spliterator.SORTED; + } } + return characteristics & SPLITERATOR_CHARACTERISTICS_MASK; } /** diff --git a/test/jdk/java/util/stream/boottest/java.base/java/util/stream/StreamOpFlagsTest.java b/test/jdk/java/util/stream/boottest/java.base/java/util/stream/StreamOpFlagsTest.java index aa47aa2a103..8d894a34234 100644 --- a/test/jdk/java/util/stream/boottest/java.base/java/util/stream/StreamOpFlagsTest.java +++ b/test/jdk/java/util/stream/boottest/java.base/java/util/stream/StreamOpFlagsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -335,20 +335,20 @@ public class StreamOpFlagsTest { } public void testSpliteratorSorted() { - class SortedEmptySpliterator implements Spliterator { - final Comparator c; + class SortedEmptySpliterator> implements Spliterator { + final Comparator c; - SortedEmptySpliterator(Comparator c) { + SortedEmptySpliterator(Comparator c) { this.c = c; } @Override - public Spliterator trySplit() { + public Spliterator trySplit() { return null; } @Override - public boolean tryAdvance(Consumer action) { + public boolean tryAdvance(Consumer action) { return false; } @@ -363,19 +363,24 @@ public class StreamOpFlagsTest { } @Override - public Comparator getComparator() { + public Comparator getComparator() { return c; } - }; + } { - int flags = StreamOpFlag.fromCharacteristics(new SortedEmptySpliterator(null)); + int flags = StreamOpFlag.fromCharacteristics(new SortedEmptySpliterator<>(null)); assertEquals(flags, StreamOpFlag.IS_SORTED); } { - int flags = StreamOpFlag.fromCharacteristics(new SortedEmptySpliterator((a, b) -> 0)); + int flags = StreamOpFlag.fromCharacteristics(new SortedEmptySpliterator<>((a, b) -> 0)); assertEquals(flags, 0); } + + { + int flags = StreamOpFlag.fromCharacteristics(new SortedEmptySpliterator(Comparator.naturalOrder())); + assertEquals(flags, StreamOpFlag.IS_SORTED); + } } } diff --git a/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/SortedOpTest.java b/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/SortedOpTest.java index 3ca690e9096..7e695f97819 100644 --- a/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/SortedOpTest.java +++ b/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/SortedOpTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package org.openjdk.tests.java.util.stream; import org.testng.annotations.Test; import java.util.*; +import java.util.Comparator; import java.util.Spliterators; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiFunction; @@ -115,10 +116,14 @@ public class SortedOpTest extends OpTestCase { Collections.reverse(to10); assertSorted(to10.stream().sorted().iterator()); + assertSorted(to10.stream().sorted(Comparator.naturalOrder()).iterator()); Spliterator s = to10.stream().sorted().spliterator(); assertTrue(s.hasCharacteristics(Spliterator.SORTED)); + s = to10.stream().sorted(Comparator.naturalOrder()).spliterator(); + assertTrue(s.hasCharacteristics(Spliterator.SORTED)); + s = to10.stream().sorted(cInteger.reversed()).spliterator(); assertFalse(s.hasCharacteristics(Spliterator.SORTED)); }