8024405: Spliterators.spliterator should support CONCURRENT characteristic
Reviewed-by: martin
--- a/jdk/src/share/classes/java/util/Spliterator.java Wed Sep 18 10:49:34 2013 -0700
+++ b/jdk/src/share/classes/java/util/Spliterator.java Thu Sep 19 20:41:54 2013 -0700
@@ -539,7 +539,7 @@
* 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
--- a/jdk/src/share/classes/java/util/Spliterators.java Wed Sep 18 10:49:34 2013 -0700
+++ b/jdk/src/share/classes/java/util/Spliterators.java Thu Sep 19 20:41:54 2013 -0700
@@ -409,16 +409,16 @@
*
* @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 @@
* @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 @@
*
* @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 @@
* @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 @@
* 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 @@
* @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 @@
* 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 @@
* @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 @@
* 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 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 @@
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 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 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 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;
}
/**
--- a/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java Wed Sep 18 10:49:34 2013 -0700
+++ b/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java Thu Sep 19 20:41:54 2013 -0700
@@ -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.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 @@
}
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");
--- a/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java Wed Sep 18 10:49:34 2013 -0700
+++ b/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java Thu Sep 19 20:41:54 2013 -0700
@@ -1159,7 +1159,7 @@
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 @@
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 @@
}
}
+ 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),