8024405: Spliterators.spliterator should support CONCURRENT characteristic
Reviewed-by: martin
This commit is contained in:
parent
3a559a7ea0
commit
0f59d418d8
@ -539,7 +539,7 @@ public interface Spliterator<T> {
|
||||
* Spliterator is expected to have a documented policy concerning the impact
|
||||
* of modifications during traversal.
|
||||
*
|
||||
* <p>A top-level Spliterator should not report {@code CONCURRENT} and
|
||||
* <p>A top-level Spliterator should not report both {@code CONCURRENT} and
|
||||
* {@code SIZED}, since the finite size, if known, may change if the source
|
||||
* is concurrently modified during traversal. Such a Spliterator is
|
||||
* inconsistent and no guarantees can be made about any computation using
|
||||
|
@ -409,16 +409,16 @@ public final class Spliterators {
|
||||
*
|
||||
* @param <T> Type of elements
|
||||
* @param c The collection
|
||||
* @param additionalCharacteristics Additional spliterator characteristics
|
||||
* of this spliterator's source or elements beyond {@code SIZED} and
|
||||
* {@code SUBSIZED} which are are always reported
|
||||
* @param characteristics Characteristics of this spliterator's source or
|
||||
* elements. The characteristics {@code SIZED} and {@code SUBSIZED}
|
||||
* are additionally reported unless {@code CONCURRENT} is supplied.
|
||||
* @return A spliterator from an iterator
|
||||
* @throws NullPointerException if the given collection is {@code null}
|
||||
*/
|
||||
public static <T> Spliterator<T> spliterator(Collection<? extends T> c,
|
||||
int additionalCharacteristics) {
|
||||
int characteristics) {
|
||||
return new IteratorSpliterator<>(Objects.requireNonNull(c),
|
||||
additionalCharacteristics);
|
||||
characteristics);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -439,17 +439,17 @@ public final class Spliterators {
|
||||
* @param iterator The iterator for the source
|
||||
* @param size The number of elements in the source, to be reported as
|
||||
* initial {@code estimateSize}
|
||||
* @param additionalCharacteristics Additional spliterator characteristics
|
||||
* of this spliterator's source or elements beyond {@code SIZED} and
|
||||
* {@code SUBSIZED} which are are always reported
|
||||
* @param characteristics Characteristics of this spliterator's source or
|
||||
* elements. The characteristics {@code SIZED} and {@code SUBSIZED}
|
||||
* are additionally reported unless {@code CONCURRENT} is supplied.
|
||||
* @return A spliterator from an iterator
|
||||
* @throws NullPointerException if the given iterator is {@code null}
|
||||
*/
|
||||
public static <T> Spliterator<T> spliterator(Iterator<? extends T> iterator,
|
||||
long size,
|
||||
int additionalCharacteristics) {
|
||||
int characteristics) {
|
||||
return new IteratorSpliterator<>(Objects.requireNonNull(iterator), size,
|
||||
additionalCharacteristics);
|
||||
characteristics);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -467,7 +467,7 @@ public final class Spliterators {
|
||||
*
|
||||
* @param <T> Type of elements
|
||||
* @param iterator The iterator for the source
|
||||
* @param characteristics Properties of this spliterator's source
|
||||
* @param characteristics Characteristics of this spliterator's source
|
||||
* or elements ({@code SIZED} and {@code SUBSIZED}, if supplied, are
|
||||
* ignored and are not reported.)
|
||||
* @return A spliterator from an iterator
|
||||
@ -496,17 +496,17 @@ public final class Spliterators {
|
||||
* @param iterator The iterator for the source
|
||||
* @param size The number of elements in the source, to be reported as
|
||||
* initial {@code estimateSize}.
|
||||
* @param additionalCharacteristics Additional spliterator characteristics
|
||||
* of this spliterator's source or elements beyond {@code SIZED} and
|
||||
* {@code SUBSIZED} which are are always reported
|
||||
* @param characteristics Characteristics of this spliterator's source or
|
||||
* elements. The characteristics {@code SIZED} and {@code SUBSIZED}
|
||||
* are additionally reported unless {@code CONCURRENT} is supplied.
|
||||
* @return A spliterator from an iterator
|
||||
* @throws NullPointerException if the given iterator is {@code null}
|
||||
*/
|
||||
public static Spliterator.OfInt spliterator(PrimitiveIterator.OfInt iterator,
|
||||
long size,
|
||||
int additionalCharacteristics) {
|
||||
int characteristics) {
|
||||
return new IntIteratorSpliterator(Objects.requireNonNull(iterator),
|
||||
size, additionalCharacteristics);
|
||||
size, characteristics);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -524,7 +524,7 @@ public final class Spliterators {
|
||||
* operated on after the spliterator is returned.
|
||||
*
|
||||
* @param iterator The iterator for the source
|
||||
* @param characteristics Properties of this spliterator's source
|
||||
* @param characteristics Characteristics of this spliterator's source
|
||||
* or elements ({@code SIZED} and {@code SUBSIZED}, if supplied, are
|
||||
* ignored and are not reported.)
|
||||
* @return A spliterator from an iterator
|
||||
@ -553,17 +553,17 @@ public final class Spliterators {
|
||||
* @param iterator The iterator for the source
|
||||
* @param size The number of elements in the source, to be reported as
|
||||
* initial {@code estimateSize}.
|
||||
* @param additionalCharacteristics Additional spliterator characteristics
|
||||
* of this spliterator's source or elements beyond {@code SIZED} and
|
||||
* {@code SUBSIZED} which are are always reported
|
||||
* @param characteristics Characteristics of this spliterator's source or
|
||||
* elements. The characteristics {@code SIZED} and {@code SUBSIZED}
|
||||
* are additionally reported unless {@code CONCURRENT} is supplied.
|
||||
* @return A spliterator from an iterator
|
||||
* @throws NullPointerException if the given iterator is {@code null}
|
||||
*/
|
||||
public static Spliterator.OfLong spliterator(PrimitiveIterator.OfLong iterator,
|
||||
long size,
|
||||
int additionalCharacteristics) {
|
||||
int characteristics) {
|
||||
return new LongIteratorSpliterator(Objects.requireNonNull(iterator),
|
||||
size, additionalCharacteristics);
|
||||
size, characteristics);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -581,7 +581,7 @@ public final class Spliterators {
|
||||
* operated on after the spliterator is returned.
|
||||
*
|
||||
* @param iterator The iterator for the source
|
||||
* @param characteristics Properties of this spliterator's source
|
||||
* @param characteristics Characteristics of this spliterator's source
|
||||
* or elements ({@code SIZED} and {@code SUBSIZED}, if supplied, are
|
||||
* ignored and are not reported.)
|
||||
* @return A spliterator from an iterator
|
||||
@ -610,17 +610,17 @@ public final class Spliterators {
|
||||
* @param iterator The iterator for the source
|
||||
* @param size The number of elements in the source, to be reported as
|
||||
* initial {@code estimateSize}
|
||||
* @param additionalCharacteristics Additional spliterator characteristics
|
||||
* of this spliterator's source or elements beyond {@code SIZED} and
|
||||
* {@code SUBSIZED} which are are always reported
|
||||
* @param characteristics Characteristics of this spliterator's source or
|
||||
* elements. The characteristics {@code SIZED} and {@code SUBSIZED}
|
||||
* are additionally reported unless {@code CONCURRENT} is supplied.
|
||||
* @return A spliterator from an iterator
|
||||
* @throws NullPointerException if the given iterator is {@code null}
|
||||
*/
|
||||
public static Spliterator.OfDouble spliterator(PrimitiveIterator.OfDouble iterator,
|
||||
long size,
|
||||
int additionalCharacteristics) {
|
||||
int characteristics) {
|
||||
return new DoubleIteratorSpliterator(Objects.requireNonNull(iterator),
|
||||
size, additionalCharacteristics);
|
||||
size, characteristics);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -638,7 +638,7 @@ public final class Spliterators {
|
||||
* operated on after the spliterator is returned.
|
||||
*
|
||||
* @param iterator The iterator for the source
|
||||
* @param characteristics Properties of this spliterator's source
|
||||
* @param characteristics Characteristics of this spliterator's source
|
||||
* or elements ({@code SIZED} and {@code SUBSIZED}, if supplied, are
|
||||
* ignored and are not reported.)
|
||||
* @return A spliterator from an iterator
|
||||
@ -1710,7 +1710,9 @@ public final class Spliterators {
|
||||
public IteratorSpliterator(Collection<? extends T> collection, int characteristics) {
|
||||
this.collection = collection;
|
||||
this.it = null;
|
||||
this.characteristics = characteristics | Spliterator.SIZED | Spliterator.SUBSIZED;
|
||||
this.characteristics = (characteristics & Spliterator.CONCURRENT) == 0
|
||||
? characteristics | Spliterator.SIZED | Spliterator.SUBSIZED
|
||||
: characteristics;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1727,7 +1729,9 @@ public final class Spliterators {
|
||||
this.collection = null;
|
||||
this.it = iterator;
|
||||
this.est = size;
|
||||
this.characteristics = characteristics | Spliterator.SIZED | Spliterator.SUBSIZED;
|
||||
this.characteristics = (characteristics & Spliterator.CONCURRENT) == 0
|
||||
? characteristics | Spliterator.SIZED | Spliterator.SUBSIZED
|
||||
: characteristics;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1857,7 +1861,9 @@ public final class Spliterators {
|
||||
public IntIteratorSpliterator(PrimitiveIterator.OfInt iterator, long size, int characteristics) {
|
||||
this.it = iterator;
|
||||
this.est = size;
|
||||
this.characteristics = characteristics | Spliterator.SIZED | Spliterator.SUBSIZED;
|
||||
this.characteristics = (characteristics & Spliterator.CONCURRENT) == 0
|
||||
? characteristics | Spliterator.SIZED | Spliterator.SUBSIZED
|
||||
: characteristics;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1949,7 +1955,9 @@ public final class Spliterators {
|
||||
public LongIteratorSpliterator(PrimitiveIterator.OfLong iterator, long size, int characteristics) {
|
||||
this.it = iterator;
|
||||
this.est = size;
|
||||
this.characteristics = characteristics | Spliterator.SIZED | Spliterator.SUBSIZED;
|
||||
this.characteristics = (characteristics & Spliterator.CONCURRENT) == 0
|
||||
? characteristics | Spliterator.SIZED | Spliterator.SUBSIZED
|
||||
: characteristics;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2041,7 +2049,9 @@ public final class Spliterators {
|
||||
public DoubleIteratorSpliterator(PrimitiveIterator.OfDouble iterator, long size, int characteristics) {
|
||||
this.it = iterator;
|
||||
this.est = size;
|
||||
this.characteristics = characteristics | Spliterator.SIZED | Spliterator.SUBSIZED;
|
||||
this.characteristics = (characteristics & Spliterator.CONCURRENT) == 0
|
||||
? characteristics | Spliterator.SIZED | Spliterator.SUBSIZED
|
||||
: characteristics;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8020156 8020009 8022326 8012913
|
||||
* @bug 8020156 8020009 8022326 8012913 8024405
|
||||
* @run testng SpliteratorCharacteristics
|
||||
*/
|
||||
|
||||
@ -36,21 +36,150 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.PrimitiveIterator;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.SortedSet;
|
||||
import java.util.Spliterator;
|
||||
import java.util.Spliterators;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.DoubleStream;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.LongStream;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
@Test
|
||||
public class SpliteratorCharacteristics {
|
||||
|
||||
public void testSpliteratorFromCollection() {
|
||||
List<Integer> l = Arrays.asList(1, 2, 3, 4);
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliterator(l, 0);
|
||||
assertCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliterator(l, Spliterator.CONCURRENT);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliterator(l.iterator( ), 1, 0);
|
||||
assertCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliterator(l.iterator( ), 1, Spliterator.CONCURRENT);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliteratorUnknownSize(l.iterator( ), 0);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliteratorUnknownSize(
|
||||
l.iterator(), Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSpliteratorOfIntFromIterator() {
|
||||
Supplier<PrimitiveIterator.OfInt> si = () -> IntStream.of(1, 2, 3, 4).iterator();
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliterator(si.get(), 1, 0);
|
||||
assertCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliterator(si.get(), 1, Spliterator.CONCURRENT);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliteratorUnknownSize(si.get(), 0);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliteratorUnknownSize(
|
||||
si.get(), Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSpliteratorOfLongFromIterator() {
|
||||
Supplier<PrimitiveIterator.OfLong> si = () -> LongStream.of(1, 2, 3, 4).iterator();
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliterator(si.get(), 1, 0);
|
||||
assertCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliterator(si.get(), 1, Spliterator.CONCURRENT);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliteratorUnknownSize(si.get(), 0);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliteratorUnknownSize(
|
||||
si.get(), Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSpliteratorOfDoubleFromIterator() {
|
||||
Supplier<PrimitiveIterator.OfDouble> si = () -> DoubleStream.of(1, 2, 3, 4).iterator();
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliterator(si.get(), 1, 0);
|
||||
assertCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliterator(si.get(), 1, Spliterator.CONCURRENT);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliteratorUnknownSize(si.get(), 0);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
}
|
||||
|
||||
{
|
||||
Spliterator<?> s = Spliterators.spliteratorUnknownSize(
|
||||
si.get(), Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
public void testHashMap() {
|
||||
assertMapCharacteristics(new HashMap<>(),
|
||||
Spliterator.SIZED | Spliterator.DISTINCT);
|
||||
@ -199,10 +328,19 @@ public class SpliteratorCharacteristics {
|
||||
}
|
||||
|
||||
void assertCharacteristics(Collection<?> c, int expectedCharacteristics) {
|
||||
assertTrue(c.spliterator().hasCharacteristics(expectedCharacteristics),
|
||||
assertCharacteristics(c.spliterator(), expectedCharacteristics);
|
||||
}
|
||||
|
||||
void assertCharacteristics(Spliterator<?> s, int expectedCharacteristics) {
|
||||
assertTrue(s.hasCharacteristics(expectedCharacteristics),
|
||||
"Spliterator characteristics");
|
||||
}
|
||||
|
||||
void assertHasNotCharacteristics(Spliterator<?> s, int expectedCharacteristics) {
|
||||
assertFalse(s.hasCharacteristics(expectedCharacteristics),
|
||||
"Spliterator characteristics");
|
||||
}
|
||||
|
||||
void assertNullComparator(Collection<?> c) {
|
||||
assertNull(c.spliterator().getComparator(),
|
||||
"Comparator of Spliterator of Collection");
|
||||
|
@ -1159,7 +1159,7 @@ public class SpliteratorTraversingAndSplittingTest {
|
||||
List<T> dest = new ArrayList<>();
|
||||
spliterator = supplier.get();
|
||||
|
||||
assertSpliterator(spliterator);
|
||||
assertRootSpliterator(spliterator);
|
||||
|
||||
// verify splitting with forEach
|
||||
visit(depth, 0, dest, spliterator, boxingAdapter, spliterator.characteristics(), false);
|
||||
@ -1234,7 +1234,7 @@ public class SpliteratorTraversingAndSplittingTest {
|
||||
UnaryOperator<Consumer<T>> boxingAdapter) {
|
||||
Spliterator<T> s = supplier.get();
|
||||
boolean isOrdered = s.hasCharacteristics(Spliterator.ORDERED);
|
||||
assertSpliterator(s);
|
||||
assertRootSpliterator(s);
|
||||
|
||||
List<T> splits = new ArrayList<>();
|
||||
Consumer<T> c = boxingAdapter.apply(splits::add);
|
||||
@ -1326,6 +1326,13 @@ public class SpliteratorTraversingAndSplittingTest {
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertRootSpliterator(Spliterator<?> s) {
|
||||
assertFalse(s.hasCharacteristics(Spliterator.SIZED | Spliterator.CONCURRENT),
|
||||
"Root spliterator should not be SIZED and CONCURRENT");
|
||||
|
||||
assertSpliterator(s);
|
||||
}
|
||||
|
||||
private static void assertSpliterator(Spliterator<?> s, int rootCharacteristics) {
|
||||
if ((rootCharacteristics & Spliterator.SUBSIZED) != 0) {
|
||||
assertTrue(s.hasCharacteristics(Spliterator.SUBSIZED),
|
||||
|
Loading…
Reference in New Issue
Block a user