Skip to content
This repository was archived by the owner on Sep 19, 2023. It is now read-only.

Commit b4f19f5

Browse files
author
Stuart Marks
committed
8306785: fix deficient spliterators for Sequenced Collections
Reviewed-by: rriggs Backport-of: 743e8b8e0a9fe032a0dd652a4fef1f761af66595
1 parent 65ed787 commit b4f19f5

File tree

6 files changed

+26
-12
lines changed

6 files changed

+26
-12
lines changed

src/java.base/share/classes/java/util/ArrayList.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,7 +1509,10 @@ private void updateSizeAndModCount(int sizeChange) {
15091509
public Spliterator<E> spliterator() {
15101510
checkForComodification();
15111511

1512-
// ArrayListSpliterator not used here due to late-binding
1512+
// This Spliterator needs to late-bind to the subList, not the outer
1513+
// ArrayList. Note that it is legal for structural changes to be made
1514+
// to a subList after spliterator() is called but before any spliterator
1515+
// operations that would causing binding are performed.
15131516
return new Spliterator<E>() {
15141517
private int index = offset; // current index, modified on advance/split
15151518
private int fence = -1; // -1 until used; then one past last index
@@ -1628,9 +1631,7 @@ final class ArrayListSpliterator implements Spliterator<E> {
16281631
* be worthwhile in practice. To carry this out, we (1) lazily
16291632
* initialize fence and expectedModCount until the latest
16301633
* point that we need to commit to the state we are checking
1631-
* against; thus improving precision. (This doesn't apply to
1632-
* SubLists, that create spliterators with current non-lazy
1633-
* values). (2) We perform only a single
1634+
* against; thus improving precision. (2) We perform only a single
16341635
* ConcurrentModificationException check at the end of forEach
16351636
* (the most performance-sensitive method). When using forEach
16361637
* (as opposed to iterators), we can normally only detect

src/java.base/share/classes/java/util/ReverseOrderDequeView.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public Iterator<E> iterator() {
6161
}
6262

6363
public Spliterator<E> spliterator() {
64-
return Spliterators.spliteratorUnknownSize(base.descendingIterator(), 0);
64+
return Spliterators.spliterator(this, Spliterator.ORDERED);
6565
}
6666

6767
// ========== Collection ==========

src/java.base/share/classes/java/util/ReverseOrderListView.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,7 @@ public Iterator<E> iterator() {
151151
}
152152

153153
public Spliterator<E> spliterator() {
154-
// TODO can probably improve this
155-
return Spliterators.spliteratorUnknownSize(new DescendingIterator(), 0);
154+
return Spliterators.spliterator(this, Spliterator.ORDERED);
156155
}
157156

158157
// ========== Collection ==========

src/java.base/share/classes/java/util/ReverseOrderSortedSetView.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public Iterator<E> iterator() {
111111
}
112112

113113
public Spliterator<E> spliterator() {
114-
return Spliterators.spliteratorUnknownSize(descendingIterator(base), 0);
114+
return Spliterators.spliterator(this, Spliterator.ORDERED);
115115
}
116116

117117
// ========== Collection ==========

src/java.base/share/classes/java/util/Spliterators.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -948,10 +948,12 @@ static final class ArraySpliterator<T> implements Spliterator<T> {
948948
private int index; // current index, modified on advance/split
949949
private final int fence; // one past last index
950950
private final int characteristics;
951-
private long estimatedSize; // estimated size, to help to split evenly
951+
private long estimatedSize; // if >= 0, the estimated size, to help to split evenly
952+
// if -1, exact size is known to be fence - index
952953

953954
/**
954955
* Creates a spliterator covering all of the given array.
956+
* Its size is known exactly and it is SIZED and SUBSIZED.
955957
* @param array the array, assumed to be unmodified during use
956958
* @param additionalCharacteristics Additional spliterator characteristics
957959
* of this spliterator's source or elements beyond {@code SIZED} and
@@ -962,7 +964,8 @@ public ArraySpliterator(Object[] array, int additionalCharacteristics) {
962964
}
963965

964966
/**
965-
* Creates a spliterator covering the given array and range
967+
* Creates a spliterator covering the given array and range.
968+
* Its size is known exactly and it is SIZED and SUBSIZED.
966969
* @param array the array, assumed to be unmodified during use
967970
* @param origin the least index (inclusive) to cover
968971
* @param fence one past the greatest index to cover
@@ -978,6 +981,18 @@ public ArraySpliterator(Object[] array, int origin, int fence, int additionalCha
978981
this.estimatedSize = -1;
979982
}
980983

984+
/**
985+
* Creates a spliterator covering the given array and range but that is
986+
* not SIZED or SUBSIZED. This case occurs as a result of splitting another
987+
* spliterator that is not sized, so it's inappropriate for one of its
988+
* sub-spliterators to be sized.
989+
* @param array the array, assumed to be unmodified during use
990+
* @param origin the least index (inclusive) to cover
991+
* @param fence one past the greatest index to cover
992+
* @param characteristics characteristics of this spliterator's source; {@code SIZED} and
993+
* {@code SUBSIZED} are removed if present
994+
* @param estimatedSize the size estimate; should always be nonnegative
995+
*/
981996
private ArraySpliterator(Object[] array, int origin, int fence, int characteristics, long estimatedSize) {
982997
this.array = array;
983998
this.index = origin;

src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1822,8 +1822,7 @@ public Iterator<E> iterator() {
18221822
}
18231823

18241824
public Spliterator<E> spliterator() {
1825-
// TODO can probably improve this
1826-
return Spliterators.spliteratorUnknownSize(new DescendingIterator(), 0);
1825+
return Spliterators.spliterator(this, Spliterator.ORDERED);
18271826
}
18281827

18291828
// ========== Collection ==========

0 commit comments

Comments
 (0)