Return null from Spliterator.getComparator() for natural ordering (fixes #6187)#8375
Open
holly-agyei wants to merge 2 commits intogoogle:masterfrom
Open
Return null from Spliterator.getComparator() for natural ordering (fixes #6187)#8375holly-agyei wants to merge 2 commits intogoogle:masterfrom
holly-agyei wants to merge 2 commits intogoogle:masterfrom
Conversation
Per the Spliterator.getComparator() contract, implementations whose source
is sorted in natural order must return null. The JDK uses this signal to
clear the SORTED characteristic when the comparator is non-null, which in
turn disables Stream.sorted()'s short-circuit optimization (SortedOps line
136-139), causing unnecessary re-sorting of already-sorted data.
ImmutableSortedSet.spliterator() and CollectSpliterators.indexed() (used
by ImmutableSortedAsList.spliterator()) returned Ordering.natural() instead
of null for naturally-ordered sources, so code like
ImmutableSortedSet.of(1, 2, 3, 4).stream().sorted().collect(toList());
incurred a full re-sort rather than a no-op.
This change normalizes the two well-known natural-ordering singletons
(Ordering.natural() and Comparator.naturalOrder()) to null at the
getComparator() boundary via a shared CollectSpliterators.isNaturalOrder()
helper. Custom and reverse-order comparators are preserved unchanged.
Fixes google#6187.
Made-with: Cursor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #6187.
Problem
Per the
Spliterator.getComparator()contract, implementations whose source is sorted in natural order must returnnull. The JDK uses this signal to clear theSORTEDcharacteristic when the comparator is non-null (StreamOpFlag line 751-755), which in turn disablesStream.sorted()'s short-circuit optimization, causing unnecessary re-sorting of already-sorted data.ImmutableSortedSet.spliterator()andCollectSpliterators.indexed()(used byImmutableSortedAsList.spliterator(), which in turn backsRegularImmutableSortedSet.spliterator()and its subset views) returnedOrdering.natural()instead ofnullfor naturally-ordered sources, so code like:incurred a full re-sort rather than the documented no-op.
Fix
CollectSpliterators.isNaturalOrder(Comparator), a shared helper that recognizes the two well-known natural-ordering singletons (Ordering.natural()andComparator.naturalOrder()) as well asnull.CollectSpliterators.indexed()andImmutableSortedSet.spliterator()now normalize natural-ordering comparators tonullat thegetComparator()boundary. Custom and reverse-order comparators are preserved unchanged, soDescendingImmutableSortedSetand user-supplied comparators are unaffected.@kevinb9n called out special-casing
Comparator.naturalOrder()in addition toOrdering.natural()on #6188 (the earlier, stale attempt by @kilink); this PR honors that and adds the test coverage that was missing from both #6188 and the withdrawn #8174.Tests
Added regression tests at two levels:
CollectSpliteratorsTesttestIsNaturalOrder_null,_orderingNatural,_comparatorNaturalOrder— helper returnstruefor each natural-ordering formtestIsNaturalOrder_reverseOrder_false,_customComparator_false— non-natural comparators are rejectedtestIndexedSortedSpliterator_naturalOrderReturnsNull,_comparatorNaturalOrderReturnsNull— indexed spliterator surfacesnullfor natural ordering and keepsSORTEDtestIndexedSortedSpliterator_customComparatorIsPreserved— custom comparator round-trips unchangedImmutableSortedSetTesttestSpliteratorGetComparator_naturalOrdering_returnsNulltestSpliteratorGetComparator_comparatorNaturalOrder_returnsNulltestSpliteratorGetComparator_customOrdering_returnsComparatortestSpliteratorHasSortedCharacteristictestAsListSpliteratorGetComparator_naturalOrdering_returnsNull(covers theImmutableSortedAsListpath used byRegularImmutableSortedSet)testAsListSpliteratorGetComparator_customOrdering_returnsComparatorTest plan
./mvnw -pl guava -am install -DskipTests— builds clean./mvnw -pl guava-tests test -Dtest='CollectSpliteratorsTest,ImmutableSortedSetTest'— 17,293 tests, 0 failures./mvnw -pl guava-tests test -Dtest='*SortedSet*,*SortedMap*,*SortedMultiset*,*Collect*Test,ImmutableListTest,ImmutableSetTest,StreamsTest'— 455,720 tests, 0 failuresPer
CONTRIBUTING.md, theandroid/tree is left to the automatic mirror script.