diff -r b2d8b5f308e7 -r e897ad52979e jdk/src/share/classes/java/util/stream/Streams.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/util/stream/Streams.java Sat Apr 20 18:53:26 2013 -0400 @@ -0,0 +1,656 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.util.stream; + +import java.util.Comparator; +import java.util.Iterator; +import java.util.Objects; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.DoubleConsumer; +import java.util.function.IntConsumer; +import java.util.function.LongConsumer; + +/** + * Utility methods for operating on and creating streams. + * + *
Unless otherwise stated, streams are created as sequential streams. A + * sequential stream can be transformed into a parallel stream by calling the + * {@code parallel()} method on the created stream. + * + * @since 1.8 + */ +class Streams { + + private Streams() { + throw new Error("no instances"); + } + + /** + * An object instance representing no value, that cannot be an actual + * data element of a stream. Used when processing streams that can contain + * {@code null} elements to distinguish between a {@code null} value and no + * value. + */ + static final Object NONE = new Object(); + + /** + * An {@code int} range spliterator. + */ + static final class RangeIntSpliterator implements Spliterator.OfInt { + private int from; + private final int upTo; + private final int step; + + RangeIntSpliterator(int from, int upTo, int step) { + this.from = from; + this.upTo = upTo; + this.step = step; + } + + @Override + public boolean tryAdvance(IntConsumer consumer) { + boolean hasNext = from < upTo; + if (hasNext) { + consumer.accept(from); + from += step; + } + return hasNext; + } + + @Override + public void forEachRemaining(IntConsumer consumer) { + int hUpTo = upTo; + int hStep = step; // hoist accesses and checks from loop + for (int i = from; i < hUpTo; i += hStep) + consumer.accept(i); + from = upTo; + } + + @Override + public long estimateSize() { + int d = upTo - from; + return (d / step) + ((d % step == 0) ? 0 : 1); + } + + @Override + public int characteristics() { + return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED | + Spliterator.IMMUTABLE | Spliterator.NONNULL | + Spliterator.DISTINCT | Spliterator.SORTED; + } + + @Override + public Comparator super Integer> getComparator() { + return null; + } + + @Override + public Spliterator.OfInt trySplit() { + return estimateSize() <= 1 + ? null + : new RangeIntSpliterator(from, from = from + midPoint(), step); + } + + private int midPoint() { + // Size is known to be >= 2 + int bisection = (upTo - from) / 2; + // If bisection > step then round down to nearest multiple of step + // otherwise round up to step + return bisection > step ? bisection - bisection % step : step; + } + } + + /** + * A {@code long} range spliterator. + */ + static final class RangeLongSpliterator implements Spliterator.OfLong { + private long from; + private final long upTo; + private final long step; + + RangeLongSpliterator(long from, long upTo, long step) { + this.from = from; + this.upTo = upTo; + this.step = step; + } + + @Override + public boolean tryAdvance(LongConsumer consumer) { + boolean hasNext = from < upTo; + if (hasNext) { + consumer.accept(from); + from += step; + } + return hasNext; + } + + @Override + public void forEachRemaining(LongConsumer consumer) { + long hUpTo = upTo; + long hStep = step; // hoist accesses and checks from loop + for (long i = from; i < hUpTo; i += hStep) + consumer.accept(i); + from = upTo; + } + + @Override + public long estimateSize() { + long d = upTo - from; + return (d / step) + ((d % step == 0) ? 0 : 1); + } + + @Override + public int characteristics() { + return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED | + Spliterator.IMMUTABLE | Spliterator.NONNULL | + Spliterator.DISTINCT | Spliterator.SORTED; + } + + @Override + public Comparator super Long> getComparator() { + return null; + } + + @Override + public Spliterator.OfLong trySplit() { + return estimateSize() <= 1 + ? null + : new RangeLongSpliterator(from, from = from + midPoint(), step); + } + + private long midPoint() { + // Size is known to be >= 2 + long bisection = (upTo - from) / 2; + // If bisection > step then round down to nearest multiple of step + // otherwise round up to step + return bisection > step ? bisection - bisection % step : step; + } + } + + /** + * A {@code double} range spliterator. + * + *
The traversing and splitting logic is equivalent to that of + * {@code RangeLongSpliterator} for increasing values with a {@code step} of + * {@code 1}. + * + *
A {@code double} value is calculated from the function
+ * {@code start + i * step} where {@code i} is the absolute position of the
+ * value when traversing an instance of this class that has not been split.
+ * This ensures the same values are produced at the same absolute positions
+ * regardless of how an instance of this class is split or traversed.
+ */
+ static final class RangeDoubleSpliterator implements Spliterator.OfDouble {
+ private final double from;
+ private final double upTo;
+ private final double step;
+
+ private long lFrom;
+ private final long lUpTo;
+
+ RangeDoubleSpliterator(double from, double upTo, double step, long lFrom, long lUpTo) {
+ this.from = from;
+ this.upTo = upTo;
+ this.step = step;
+ this.lFrom = lFrom;
+ this.lUpTo = lUpTo;
+ }
+
+ @Override
+ public boolean tryAdvance(DoubleConsumer consumer) {
+ boolean hasNext = lFrom < lUpTo;
+ if (hasNext) {
+ consumer.accept(from + lFrom * step);
+ lFrom++;
+ }
+ return hasNext;
+ }
+
+ @Override
+ public void forEachRemaining(DoubleConsumer consumer) {
+ double hOrigin = from;
+ double hStep = step;
+ long hLUpTo = lUpTo;
+ long i = lFrom;
+ for (; i < hLUpTo; i++) {
+ consumer.accept(hOrigin + i * hStep);
+ }
+ lFrom = i;
+ }
+
+ @Override
+ public long estimateSize() {
+ return lUpTo - lFrom;
+ }
+
+ @Override
+ public int characteristics() {
+ return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED |
+ Spliterator.IMMUTABLE | Spliterator.NONNULL |
+ Spliterator.DISTINCT | Spliterator.SORTED;
+ }
+
+ @Override
+ public Comparator super Double> getComparator() {
+ return null;
+ }
+
+ @Override
+ public Spliterator.OfDouble trySplit() {
+ return estimateSize() <= 1
+ ? null
+ : new RangeDoubleSpliterator(from, upTo, step, lFrom, lFrom = lFrom + midPoint());
+ }
+
+ private long midPoint() {
+ // Size is known to be >= 2
+ return (lUpTo - lFrom) / 2;
+ }
+ }
+
+ private static abstract class AbstractStreamBuilderImpl