提交 dca3f55a 编写于 作者: P psandoz

8024405: Spliterators.spliterator should support CONCURRENT characteristic

Reviewed-by: martin
上级 5347d042
...@@ -539,7 +539,7 @@ public interface Spliterator<T> { ...@@ -539,7 +539,7 @@ public interface Spliterator<T> {
* Spliterator is expected to have a documented policy concerning the impact * Spliterator is expected to have a documented policy concerning the impact
* of modifications during traversal. * 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 * {@code SIZED}, since the finite size, if known, may change if the source
* is concurrently modified during traversal. Such a Spliterator is * is concurrently modified during traversal. Such a Spliterator is
* inconsistent and no guarantees can be made about any computation using * inconsistent and no guarantees can be made about any computation using
......
...@@ -409,16 +409,16 @@ public final class Spliterators { ...@@ -409,16 +409,16 @@ public final class Spliterators {
* *
* @param <T> Type of elements * @param <T> Type of elements
* @param c The collection * @param c The collection
* @param additionalCharacteristics Additional spliterator characteristics * @param characteristics Characteristics of this spliterator's source or
* of this spliterator's source or elements beyond {@code SIZED} and * elements. The characteristics {@code SIZED} and {@code SUBSIZED}
* {@code SUBSIZED} which are are always reported * are additionally reported unless {@code CONCURRENT} is supplied.
* @return A spliterator from an iterator * @return A spliterator from an iterator
* @throws NullPointerException if the given collection is {@code null} * @throws NullPointerException if the given collection is {@code null}
*/ */
public static <T> Spliterator<T> spliterator(Collection<? extends T> c, public static <T> Spliterator<T> spliterator(Collection<? extends T> c,
int additionalCharacteristics) { int characteristics) {
return new IteratorSpliterator<>(Objects.requireNonNull(c), return new IteratorSpliterator<>(Objects.requireNonNull(c),
additionalCharacteristics); characteristics);
} }
/** /**
...@@ -439,17 +439,17 @@ public final class Spliterators { ...@@ -439,17 +439,17 @@ public final class Spliterators {
* @param iterator The iterator for the source * @param iterator The iterator for the source
* @param size The number of elements in the source, to be reported as * @param size The number of elements in the source, to be reported as
* initial {@code estimateSize} * initial {@code estimateSize}
* @param additionalCharacteristics Additional spliterator characteristics * @param characteristics Characteristics of this spliterator's source or
* of this spliterator's source or elements beyond {@code SIZED} and * elements. The characteristics {@code SIZED} and {@code SUBSIZED}
* {@code SUBSIZED} which are are always reported * are additionally reported unless {@code CONCURRENT} is supplied.
* @return A spliterator from an iterator * @return A spliterator from an iterator
* @throws NullPointerException if the given iterator is {@code null} * @throws NullPointerException if the given iterator is {@code null}
*/ */
public static <T> Spliterator<T> spliterator(Iterator<? extends T> iterator, public static <T> Spliterator<T> spliterator(Iterator<? extends T> iterator,
long size, long size,
int additionalCharacteristics) { int characteristics) {
return new IteratorSpliterator<>(Objects.requireNonNull(iterator), size, return new IteratorSpliterator<>(Objects.requireNonNull(iterator), size,
additionalCharacteristics); characteristics);
} }
/** /**
...@@ -467,7 +467,7 @@ public final class Spliterators { ...@@ -467,7 +467,7 @@ public final class Spliterators {
* *
* @param <T> Type of elements * @param <T> Type of elements
* @param iterator The iterator for the source * @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 * or elements ({@code SIZED} and {@code SUBSIZED}, if supplied, are
* ignored and are not reported.) * ignored and are not reported.)
* @return A spliterator from an iterator * @return A spliterator from an iterator
...@@ -496,17 +496,17 @@ public final class Spliterators { ...@@ -496,17 +496,17 @@ public final class Spliterators {
* @param iterator The iterator for the source * @param iterator The iterator for the source
* @param size The number of elements in the source, to be reported as * @param size The number of elements in the source, to be reported as
* initial {@code estimateSize}. * initial {@code estimateSize}.
* @param additionalCharacteristics Additional spliterator characteristics * @param characteristics Characteristics of this spliterator's source or
* of this spliterator's source or elements beyond {@code SIZED} and * elements. The characteristics {@code SIZED} and {@code SUBSIZED}
* {@code SUBSIZED} which are are always reported * are additionally reported unless {@code CONCURRENT} is supplied.
* @return A spliterator from an iterator * @return A spliterator from an iterator
* @throws NullPointerException if the given iterator is {@code null} * @throws NullPointerException if the given iterator is {@code null}
*/ */
public static Spliterator.OfInt spliterator(PrimitiveIterator.OfInt iterator, public static Spliterator.OfInt spliterator(PrimitiveIterator.OfInt iterator,
long size, long size,
int additionalCharacteristics) { int characteristics) {
return new IntIteratorSpliterator(Objects.requireNonNull(iterator), return new IntIteratorSpliterator(Objects.requireNonNull(iterator),
size, additionalCharacteristics); size, characteristics);
} }
/** /**
...@@ -524,7 +524,7 @@ public final class Spliterators { ...@@ -524,7 +524,7 @@ public final class Spliterators {
* operated on after the spliterator is returned. * operated on after the spliterator is returned.
* *
* @param iterator The iterator for the source * @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 * or elements ({@code SIZED} and {@code SUBSIZED}, if supplied, are
* ignored and are not reported.) * ignored and are not reported.)
* @return A spliterator from an iterator * @return A spliterator from an iterator
...@@ -553,17 +553,17 @@ public final class Spliterators { ...@@ -553,17 +553,17 @@ public final class Spliterators {
* @param iterator The iterator for the source * @param iterator The iterator for the source
* @param size The number of elements in the source, to be reported as * @param size The number of elements in the source, to be reported as
* initial {@code estimateSize}. * initial {@code estimateSize}.
* @param additionalCharacteristics Additional spliterator characteristics * @param characteristics Characteristics of this spliterator's source or
* of this spliterator's source or elements beyond {@code SIZED} and * elements. The characteristics {@code SIZED} and {@code SUBSIZED}
* {@code SUBSIZED} which are are always reported * are additionally reported unless {@code CONCURRENT} is supplied.
* @return A spliterator from an iterator * @return A spliterator from an iterator
* @throws NullPointerException if the given iterator is {@code null} * @throws NullPointerException if the given iterator is {@code null}
*/ */
public static Spliterator.OfLong spliterator(PrimitiveIterator.OfLong iterator, public static Spliterator.OfLong spliterator(PrimitiveIterator.OfLong iterator,
long size, long size,
int additionalCharacteristics) { int characteristics) {
return new LongIteratorSpliterator(Objects.requireNonNull(iterator), return new LongIteratorSpliterator(Objects.requireNonNull(iterator),
size, additionalCharacteristics); size, characteristics);
} }
/** /**
...@@ -581,7 +581,7 @@ public final class Spliterators { ...@@ -581,7 +581,7 @@ public final class Spliterators {
* operated on after the spliterator is returned. * operated on after the spliterator is returned.
* *
* @param iterator The iterator for the source * @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 * or elements ({@code SIZED} and {@code SUBSIZED}, if supplied, are
* ignored and are not reported.) * ignored and are not reported.)
* @return A spliterator from an iterator * @return A spliterator from an iterator
...@@ -610,17 +610,17 @@ public final class Spliterators { ...@@ -610,17 +610,17 @@ public final class Spliterators {
* @param iterator The iterator for the source * @param iterator The iterator for the source
* @param size The number of elements in the source, to be reported as * @param size The number of elements in the source, to be reported as
* initial {@code estimateSize} * initial {@code estimateSize}
* @param additionalCharacteristics Additional spliterator characteristics * @param characteristics Characteristics of this spliterator's source or
* of this spliterator's source or elements beyond {@code SIZED} and * elements. The characteristics {@code SIZED} and {@code SUBSIZED}
* {@code SUBSIZED} which are are always reported * are additionally reported unless {@code CONCURRENT} is supplied.
* @return A spliterator from an iterator * @return A spliterator from an iterator
* @throws NullPointerException if the given iterator is {@code null} * @throws NullPointerException if the given iterator is {@code null}
*/ */
public static Spliterator.OfDouble spliterator(PrimitiveIterator.OfDouble iterator, public static Spliterator.OfDouble spliterator(PrimitiveIterator.OfDouble iterator,
long size, long size,
int additionalCharacteristics) { int characteristics) {
return new DoubleIteratorSpliterator(Objects.requireNonNull(iterator), return new DoubleIteratorSpliterator(Objects.requireNonNull(iterator),
size, additionalCharacteristics); size, characteristics);
} }
/** /**
...@@ -638,7 +638,7 @@ public final class Spliterators { ...@@ -638,7 +638,7 @@ public final class Spliterators {
* operated on after the spliterator is returned. * operated on after the spliterator is returned.
* *
* @param iterator The iterator for the source * @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 * or elements ({@code SIZED} and {@code SUBSIZED}, if supplied, are
* ignored and are not reported.) * ignored and are not reported.)
* @return A spliterator from an iterator * @return A spliterator from an iterator
...@@ -1710,7 +1710,9 @@ public final class Spliterators { ...@@ -1710,7 +1710,9 @@ public final class Spliterators {
public IteratorSpliterator(Collection<? extends T> collection, int characteristics) { public IteratorSpliterator(Collection<? extends T> collection, int characteristics) {
this.collection = collection; this.collection = collection;
this.it = null; 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 { ...@@ -1727,7 +1729,9 @@ public final class Spliterators {
this.collection = null; this.collection = null;
this.it = iterator; this.it = iterator;
this.est = size; 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 { ...@@ -1857,7 +1861,9 @@ public final class Spliterators {
public IntIteratorSpliterator(PrimitiveIterator.OfInt iterator, long size, int characteristics) { public IntIteratorSpliterator(PrimitiveIterator.OfInt iterator, long size, int characteristics) {
this.it = iterator; this.it = iterator;
this.est = size; 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 { ...@@ -1949,7 +1955,9 @@ public final class Spliterators {
public LongIteratorSpliterator(PrimitiveIterator.OfLong iterator, long size, int characteristics) { public LongIteratorSpliterator(PrimitiveIterator.OfLong iterator, long size, int characteristics) {
this.it = iterator; this.it = iterator;
this.est = size; 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 { ...@@ -2041,7 +2049,9 @@ public final class Spliterators {
public DoubleIteratorSpliterator(PrimitiveIterator.OfDouble iterator, long size, int characteristics) { public DoubleIteratorSpliterator(PrimitiveIterator.OfDouble iterator, long size, int characteristics) {
this.it = iterator; this.it = iterator;
this.est = size; 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 @@ ...@@ -23,7 +23,7 @@
/** /**
* @test * @test
* @bug 8020156 8020009 8022326 8012913 * @bug 8020156 8020009 8022326 8012913 8024405
* @run testng SpliteratorCharacteristics * @run testng SpliteratorCharacteristics
*/ */
...@@ -36,21 +36,150 @@ import java.util.HashMap; ...@@ -36,21 +36,150 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.PrimitiveIterator;
import java.util.Set; import java.util.Set;
import java.util.SortedMap; import java.util.SortedMap;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.Spliterator; import java.util.Spliterator;
import java.util.Spliterators;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListMap; import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.ConcurrentSkipListSet; 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.*; import static org.testng.Assert.*;
@Test @Test
public class SpliteratorCharacteristics { 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() { public void testHashMap() {
assertMapCharacteristics(new HashMap<>(), assertMapCharacteristics(new HashMap<>(),
Spliterator.SIZED | Spliterator.DISTINCT); Spliterator.SIZED | Spliterator.DISTINCT);
...@@ -199,7 +328,16 @@ public class SpliteratorCharacteristics { ...@@ -199,7 +328,16 @@ public class SpliteratorCharacteristics {
} }
void assertCharacteristics(Collection<?> c, int expectedCharacteristics) { 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"); "Spliterator characteristics");
} }
......
...@@ -1159,7 +1159,7 @@ public class SpliteratorTraversingAndSplittingTest { ...@@ -1159,7 +1159,7 @@ public class SpliteratorTraversingAndSplittingTest {
List<T> dest = new ArrayList<>(); List<T> dest = new ArrayList<>();
spliterator = supplier.get(); spliterator = supplier.get();
assertSpliterator(spliterator); assertRootSpliterator(spliterator);
// verify splitting with forEach // verify splitting with forEach
visit(depth, 0, dest, spliterator, boxingAdapter, spliterator.characteristics(), false); visit(depth, 0, dest, spliterator, boxingAdapter, spliterator.characteristics(), false);
...@@ -1234,7 +1234,7 @@ public class SpliteratorTraversingAndSplittingTest { ...@@ -1234,7 +1234,7 @@ public class SpliteratorTraversingAndSplittingTest {
UnaryOperator<Consumer<T>> boxingAdapter) { UnaryOperator<Consumer<T>> boxingAdapter) {
Spliterator<T> s = supplier.get(); Spliterator<T> s = supplier.get();
boolean isOrdered = s.hasCharacteristics(Spliterator.ORDERED); boolean isOrdered = s.hasCharacteristics(Spliterator.ORDERED);
assertSpliterator(s); assertRootSpliterator(s);
List<T> splits = new ArrayList<>(); List<T> splits = new ArrayList<>();
Consumer<T> c = boxingAdapter.apply(splits::add); Consumer<T> c = boxingAdapter.apply(splits::add);
...@@ -1326,6 +1326,13 @@ public class SpliteratorTraversingAndSplittingTest { ...@@ -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) { private static void assertSpliterator(Spliterator<?> s, int rootCharacteristics) {
if ((rootCharacteristics & Spliterator.SUBSIZED) != 0) { if ((rootCharacteristics & Spliterator.SUBSIZED) != 0) {
assertTrue(s.hasCharacteristics(Spliterator.SUBSIZED), assertTrue(s.hasCharacteristics(Spliterator.SUBSIZED),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册