--- /dev/null 2013-03-01 08:16:39.408847848 -0800 +++ new/src/share/classes/java/util/stream/Streams.java 2013-04-23 11:32:23.460938646 -0700 @@ -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 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 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 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> implements Spliterator { + // >= 0 when building, < 0 when built + // -1 == no elements + // -2 == one element, held by first + // -3 == two or more elements, held by buffer + int count; + + // Spliterator implementation for 0 or 1 element + // count == -1 for no elements + // count == -2 for one element held by first + + @Override + public S trySplit() { + return null; + } + + @Override + public long estimateSize() { + return -count - 1; + } + + @Override + public int characteristics() { + return Spliterator.SIZED | Spliterator.SUBSIZED | + Spliterator.ORDERED | Spliterator.IMMUTABLE; + } + } + + static final class StreamBuilderImpl + extends AbstractStreamBuilderImpl> + implements StreamBuilder { + // The first element in the stream + // valid if count == 1 + T first; + + // The first and subsequent elements in the stream + // non-null if count == 2 + SpinedBuffer buffer; + + /** + * Constructor for building a stream of 0 or more elements. + */ + StreamBuilderImpl() { } + + /** + * Constructor for a singleton stream. + * + * @param t the single element + */ + StreamBuilderImpl(T t) { + first = t; + count = -2; + } + + // StreamBuilder implementation + + @Override + public void accept(T t) { + if (count == 0) { + first = t; + count++; + } + else if (count > 0) { + if (buffer == null) { + buffer = new SpinedBuffer<>(); + buffer.accept(first); + count++; + } + + buffer.accept(t); + } + else { + throw new IllegalStateException(); + } + } + + public StreamBuilder add(T t) { + accept(t); + return this; + } + + @Override + public Stream build() { + int c = count; + if (c >= 0) { + // Switch count to negative value signalling the builder is built + count = -count - 1; + // Use this spliterator if 0 or 1 elements, otherwise use + // the spliterator of the spined buffer + return (c < 2) ? StreamSupport.stream(this) : StreamSupport.stream(buffer.spliterator()); + } + + throw new IllegalStateException(); + } + + // Spliterator implementation for 0 or 1 element + // count == -1 for no elements + // count == -2 for one element held by first + + @Override + public boolean tryAdvance(Consumer action) { + if (count == -2) { + action.accept(first); + count = -1; + return true; + } + else { + return false; + } + } + + @Override + public void forEachRemaining(Consumer action) { + if (count == -2) { + action.accept(first); + count = -1; + } + } + } + + static final class IntStreamBuilderImpl + extends AbstractStreamBuilderImpl + implements StreamBuilder.OfInt, Spliterator.OfInt { + // The first element in the stream + // valid if count == 1 + int first; + + // The first and subsequent elements in the stream + // non-null if count == 2 + SpinedBuffer.OfInt buffer; + + /** + * Constructor for building a stream of 0 or more elements. + */ + IntStreamBuilderImpl() { } + + /** + * Constructor for a singleton stream. + * + * @param t the single element + */ + IntStreamBuilderImpl(int t) { + first = t; + count = -2; + } + + // StreamBuilder implementation + + @Override + public void accept(int t) { + if (count == 0) { + first = t; + count++; + } + else if (count > 0) { + if (buffer == null) { + buffer = new SpinedBuffer.OfInt(); + buffer.accept(first); + count++; + } + + buffer.accept(t); + } + else { + throw new IllegalStateException(); + } + } + + @Override + public IntStream build() { + int c = count; + if (c >= 0) { + // Switch count to negative value signalling the builder is built + count = -count - 1; + // Use this spliterator if 0 or 1 elements, otherwise use + // the spliterator of the spined buffer + return (c < 2) ? StreamSupport.intStream(this) : StreamSupport.intStream(buffer.spliterator()); + } + + throw new IllegalStateException(); + } + + // Spliterator implementation for 0 or 1 element + // count == -1 for no elements + // count == -2 for one element held by first + + @Override + public boolean tryAdvance(IntConsumer action) { + if (count == -2) { + action.accept(first); + count = -1; + return true; + } + else { + return false; + } + } + + @Override + public void forEachRemaining(IntConsumer action) { + if (count == -2) { + action.accept(first); + count = -1; + } + } + } + + static final class LongStreamBuilderImpl + extends AbstractStreamBuilderImpl + implements StreamBuilder.OfLong, Spliterator.OfLong { + // The first element in the stream + // valid if count == 1 + long first; + + // The first and subsequent elements in the stream + // non-null if count == 2 + SpinedBuffer.OfLong buffer; + + /** + * Constructor for building a stream of 0 or more elements. + */ + LongStreamBuilderImpl() { } + + /** + * Constructor for a singleton stream. + * + * @param t the single element + */ + LongStreamBuilderImpl(long t) { + first = t; + count = -2; + } + + // StreamBuilder implementation + + @Override + public void accept(long t) { + if (count == 0) { + first = t; + count++; + } + else if (count > 0) { + if (buffer == null) { + buffer = new SpinedBuffer.OfLong(); + buffer.accept(first); + count++; + } + + buffer.accept(t); + } + else { + throw new IllegalStateException(); + } + } + + @Override + public LongStream build() { + int c = count; + if (c >= 0) { + // Switch count to negative value signalling the builder is built + count = -count - 1; + // Use this spliterator if 0 or 1 elements, otherwise use + // the spliterator of the spined buffer + return (c < 2) ? StreamSupport.longStream(this) : StreamSupport.longStream(buffer.spliterator()); + } + + throw new IllegalStateException(); + } + + // Spliterator implementation for 0 or 1 element + // count == -1 for no elements + // count == -2 for one element held by first + + @Override + public boolean tryAdvance(LongConsumer action) { + if (count == -2) { + action.accept(first); + count = -1; + return true; + } + else { + return false; + } + } + + @Override + public void forEachRemaining(LongConsumer action) { + if (count == -2) { + action.accept(first); + count = -1; + } + } + } + + static final class DoubleStreamBuilderImpl + extends AbstractStreamBuilderImpl + implements StreamBuilder.OfDouble, Spliterator.OfDouble { + // The first element in the stream + // valid if count == 1 + double first; + + // The first and subsequent elements in the stream + // non-null if count == 2 + SpinedBuffer.OfDouble buffer; + + /** + * Constructor for building a stream of 0 or more elements. + */ + DoubleStreamBuilderImpl() { } + + /** + * Constructor for a singleton stream. + * + * @param t the single element + */ + DoubleStreamBuilderImpl(double t) { + first = t; + count = -2; + } + + // StreamBuilder implementation + + @Override + public void accept(double t) { + if (count == 0) { + first = t; + count++; + } + else if (count > 0) { + if (buffer == null) { + buffer = new SpinedBuffer.OfDouble(); + buffer.accept(first); + count++; + } + + buffer.accept(t); + } + else { + throw new IllegalStateException(); + } + } + + @Override + public DoubleStream build() { + int c = count; + if (c >= 0) { + // Switch count to negative value signalling the builder is built + count = -count - 1; + // Use this spliterator if 0 or 1 elements, otherwise use + // the spliterator of the spined buffer + return (c < 2) ? StreamSupport.doubleStream(this) : StreamSupport.doubleStream(buffer.spliterator()); + } + + throw new IllegalStateException(); + } + + // Spliterator implementation for 0 or 1 element + // count == -1 for no elements + // count == -2 for one element held by first + + @Override + public boolean tryAdvance(DoubleConsumer action) { + if (count == -2) { + action.accept(first); + count = -1; + return true; + } + else { + return false; + } + } + + @Override + public void forEachRemaining(DoubleConsumer action) { + if (count == -2) { + action.accept(first); + count = -1; + } + } + } +}