8306785: fix deficient spliterators for Sequenced Collections
Reviewed-by: psandoz
This commit is contained in:
parent
372d0cf752
commit
743e8b8e0a
src/java.base/share/classes/java/util
@ -1509,7 +1509,10 @@ public class ArrayList<E> extends AbstractList<E>
|
||||
public Spliterator<E> spliterator() {
|
||||
checkForComodification();
|
||||
|
||||
// ArrayListSpliterator not used here due to late-binding
|
||||
// This Spliterator needs to late-bind to the subList, not the outer
|
||||
// ArrayList. Note that it is legal for structural changes to be made
|
||||
// to a subList after spliterator() is called but before any spliterator
|
||||
// operations that would causing binding are performed.
|
||||
return new Spliterator<E>() {
|
||||
private int index = offset; // current index, modified on advance/split
|
||||
private int fence = -1; // -1 until used; then one past last index
|
||||
@ -1628,9 +1631,7 @@ public class ArrayList<E> extends AbstractList<E>
|
||||
* be worthwhile in practice. To carry this out, we (1) lazily
|
||||
* initialize fence and expectedModCount until the latest
|
||||
* point that we need to commit to the state we are checking
|
||||
* against; thus improving precision. (This doesn't apply to
|
||||
* SubLists, that create spliterators with current non-lazy
|
||||
* values). (2) We perform only a single
|
||||
* against; thus improving precision. (2) We perform only a single
|
||||
* ConcurrentModificationException check at the end of forEach
|
||||
* (the most performance-sensitive method). When using forEach
|
||||
* (as opposed to iterators), we can normally only detect
|
||||
|
@ -61,7 +61,7 @@ class ReverseOrderDequeView<E> implements Deque<E> {
|
||||
}
|
||||
|
||||
public Spliterator<E> spliterator() {
|
||||
return Spliterators.spliteratorUnknownSize(base.descendingIterator(), 0);
|
||||
return Spliterators.spliterator(this, Spliterator.ORDERED);
|
||||
}
|
||||
|
||||
// ========== Collection ==========
|
||||
|
@ -151,8 +151,7 @@ class ReverseOrderListView<E> implements List<E> {
|
||||
}
|
||||
|
||||
public Spliterator<E> spliterator() {
|
||||
// TODO can probably improve this
|
||||
return Spliterators.spliteratorUnknownSize(new DescendingIterator(), 0);
|
||||
return Spliterators.spliterator(this, Spliterator.ORDERED);
|
||||
}
|
||||
|
||||
// ========== Collection ==========
|
||||
|
@ -111,7 +111,7 @@ class ReverseOrderSortedSetView<E> implements SortedSet<E> {
|
||||
}
|
||||
|
||||
public Spliterator<E> spliterator() {
|
||||
return Spliterators.spliteratorUnknownSize(descendingIterator(base), 0);
|
||||
return Spliterators.spliterator(this, Spliterator.ORDERED);
|
||||
}
|
||||
|
||||
// ========== Collection ==========
|
||||
|
@ -948,10 +948,12 @@ public final class Spliterators {
|
||||
private int index; // current index, modified on advance/split
|
||||
private final int fence; // one past last index
|
||||
private final int characteristics;
|
||||
private long estimatedSize; // estimated size, to help to split evenly
|
||||
private long estimatedSize; // if >= 0, the estimated size, to help to split evenly
|
||||
// if -1, exact size is known to be fence - index
|
||||
|
||||
/**
|
||||
* Creates a spliterator covering all of the given array.
|
||||
* Its size is known exactly and it is SIZED and SUBSIZED.
|
||||
* @param array the array, assumed to be unmodified during use
|
||||
* @param additionalCharacteristics Additional spliterator characteristics
|
||||
* of this spliterator's source or elements beyond {@code SIZED} and
|
||||
@ -962,7 +964,8 @@ public final class Spliterators {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a spliterator covering the given array and range
|
||||
* Creates a spliterator covering the given array and range.
|
||||
* Its size is known exactly and it is SIZED and SUBSIZED.
|
||||
* @param array the array, assumed to be unmodified during use
|
||||
* @param origin the least index (inclusive) to cover
|
||||
* @param fence one past the greatest index to cover
|
||||
@ -978,6 +981,18 @@ public final class Spliterators {
|
||||
this.estimatedSize = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a spliterator covering the given array and range but that is
|
||||
* not SIZED or SUBSIZED. This case occurs as a result of splitting another
|
||||
* spliterator that is not sized, so it's inappropriate for one of its
|
||||
* sub-spliterators to be sized.
|
||||
* @param array the array, assumed to be unmodified during use
|
||||
* @param origin the least index (inclusive) to cover
|
||||
* @param fence one past the greatest index to cover
|
||||
* @param characteristics characteristics of this spliterator's source; {@code SIZED} and
|
||||
* {@code SUBSIZED} are removed if present
|
||||
* @param estimatedSize the size estimate; should always be nonnegative
|
||||
*/
|
||||
private ArraySpliterator(Object[] array, int origin, int fence, int characteristics, long estimatedSize) {
|
||||
this.array = array;
|
||||
this.index = origin;
|
||||
|
@ -1822,8 +1822,7 @@ public class CopyOnWriteArrayList<E>
|
||||
}
|
||||
|
||||
public Spliterator<E> spliterator() {
|
||||
// TODO can probably improve this
|
||||
return Spliterators.spliteratorUnknownSize(new DescendingIterator(), 0);
|
||||
return Spliterators.spliterator(this, Spliterator.ORDERED);
|
||||
}
|
||||
|
||||
// ========== Collection ==========
|
||||
|
Loading…
x
Reference in New Issue
Block a user