All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.speedment.common.singletonstream.SingletonStream Maven / Gradle / Ivy

Go to download

A Speedment bundle that shades all dependencies into one jar. This is useful when deploying an application on a server.

The newest version!
/*
 *
 * Copyright (c) 2006-2019, Speedment, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); You may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.speedment.common.singletonstream;

import static com.speedment.common.singletonstream.internal.SingletonUtil.STRICT;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Objects;
import static java.util.Objects.requireNonNull;
import java.util.Optional;
import java.util.Spliterator;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.stream.Collector;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;

/**
 * An implementation of a Stream that takes exactly one element as its source.
 *
 * This implementation supports optimized implementations of most terminal
 * operations and a some number of intermediate operations.
 * 

* With STRICT mode true, un-optimized intermediate operations just * returns a wrapped standard Stream implementation. With STRICT mode * false, most intermediate operation will be executed eagerly and * will return another optimized SingletonStream. * * For performance reasons, the Stream does not throw an IllegalStateOperation * if methods are called after a terminal operation has been called on the * Stream. This could be implemented using a boolean value set by each * terminating op. All other ops could then assert this flag. * * @author Per Minborg * @param the type of the stream elements */ public final class SingletonStream implements Stream { private final T element; private SingletonStream(T element) { this.element = element; } /** * Creates and returns an optimized sequential {@link Stream} implementation * with only a single element. * * @param element the single element * @param the type of the stream elements * @return a singleton sequential stream */ public static SingletonStream of(T element) { return new SingletonStream<>(element); } /** * Creates and returns an optimized sequential {@link Stream} implementation * with only a single element if the element is non-null. if the element is * null, an empty Stream is returned. * * @param element the single element or null * @param the type of the stream elements * @return a singleton sequential stream */ public static Stream ofNullable(T element) { return element == null ? empty() : of(element); } @Override public Stream filter(Predicate predicate) { requireNonNull(predicate); if (STRICT) { return toStream().filter(predicate); } return predicate.test(element) ? this : empty(); } @Override public Stream map(Function mapper) { requireNonNull(mapper); if (STRICT) { return toStream().map(mapper); } return of(mapper.apply(element)); } @Override public IntStream mapToInt(ToIntFunction mapper) { requireNonNull(mapper); if (STRICT) { return toStream().mapToInt(mapper); } return SingletonIntStream.of(mapper.applyAsInt(element)); } @Override public LongStream mapToLong(ToLongFunction mapper) { requireNonNull(mapper); if (STRICT) { return toStream().mapToLong(mapper); } return SingletonLongStream.of(mapper.applyAsLong(element)); } @Override public DoubleStream mapToDouble(ToDoubleFunction mapper) { requireNonNull(mapper); if (STRICT) { return toStream().mapToDouble(mapper); } return DoubleStream.of(mapper.applyAsDouble(element)); } @Override public Stream flatMap(Function> mapper) { requireNonNull(mapper); if (STRICT) { return toStream().flatMap(mapper); } @SuppressWarnings("unchecked") final Stream result = (Stream) mapper.apply(element); return result; } @Override public IntStream flatMapToInt(Function mapper) { requireNonNull(mapper); if (STRICT) { return toStream().flatMapToInt(mapper); } return mapper.apply(element); } @Override public LongStream flatMapToLong(Function mapper) { requireNonNull(mapper); if (STRICT) { return toStream().flatMapToLong(mapper); } return mapper.apply(element); } @Override public DoubleStream flatMapToDouble(Function mapper) { requireNonNull(mapper); if (STRICT) { return toStream().flatMapToDouble(mapper); } return mapper.apply(element); } @Override public SingletonStream distinct() { return this; } @Override public SingletonStream sorted() { return this; } @Override public SingletonStream sorted(Comparator comparator) { return this; } @Override public Stream peek(Consumer action) { return toStream().peek(action); } @Override public Stream limit(long maxSize) { if (maxSize == 0) { return empty(); // Optimization } if (maxSize > 0) { return this; } throw new IllegalArgumentException(Long.toString(maxSize)); } @Override public Stream skip(long n) { if (n == 0) { return this; // Optimization } if (n > 0) { return empty(); } throw new IllegalArgumentException(Long.toString(n)); } @Override public void forEach(Consumer action) { requireNonNull(action); action.accept(element); } @Override public void forEachOrdered(Consumer action) { requireNonNull(action); action.accept(element); } @Override public Object[] toArray() { return toArray(Object[]::new); } @SuppressWarnings("unchecked") @Override public A[] toArray(IntFunction generator) { requireNonNull(generator); final A[] result = generator.apply(1); result[0] = (A) element; return result; } @Override public T reduce(T identity, BinaryOperator accumulator) { requireNonNull(accumulator); return accumulator.apply(identity, element); } @Override public Optional reduce(BinaryOperator accumulator) { // Just one element so the accumulator is never called. return toOptional(); } @Override public U reduce(U identity, BiFunction accumulator, BinaryOperator combiner) { requireNonNull(accumulator); // the combiner is never used in a non-parallell stream return accumulator.apply(identity, element); } @Override public R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner) { requireNonNull(supplier); requireNonNull(accumulator); final R value = supplier.get(); accumulator.accept(value, element); // the combiner is never used in a non-parallell stream return value; } @Override public R collect(Collector collector) { requireNonNull(collector); final A value = collector.supplier().get(); collector.accumulator().accept(value, element); // the combiner is never used in a non-parallell stream return collector.finisher().apply(value); } @Override public Optional min(Comparator comparator) { return toOptional(); } @Override public Optional max(Comparator comparator) { return toOptional(); } @Override public long count() { return 1; } @Override public boolean anyMatch(Predicate predicate) { requireNonNull(predicate); return predicate.test(element); } @Override public boolean allMatch(Predicate predicate) { requireNonNull(predicate); return predicate.test(element); } @Override public boolean noneMatch(Predicate predicate) { requireNonNull(predicate); return !predicate.test(element); } @Override public Optional findFirst() { return toOptional(); } @Override public Optional findAny() { return toOptional(); } @Override public Iterator iterator() { return singletonIterator(element); } @Override public Spliterator spliterator() { return singletonSpliterator(element); } @Override public boolean isParallel() { return false; } @Override public SingletonStream sequential() { return this; } @Override public Stream parallel() { return toStream().parallel(); } @Override public Stream unordered() { return this; // Todo: may convey to singletonSpliterator() } @Override public Stream onClose(Runnable closeHandler) { return toStream().onClose(closeHandler); } @Override public void close() { // do nothing. OnClose createa a real Stream } /** * Make the problem someone else's... * * @return A "real" Stream with the single element */ private Stream toStream() { return Stream.of(element); } private Optional toOptional() { // if element is null, Optional will throw an NPE // just as the standard Stream implementation does. return Optional.of(element); } private static Stream empty() { return Stream.empty(); } public static Iterator singletonIterator(final E e) { return new Iterator() { private boolean hasNext = true; @Override public boolean hasNext() { return hasNext; } @Override public E next() { if (hasNext) { hasNext = false; return e; } throw new NoSuchElementException(); } @Override public void remove() { throw new UnsupportedOperationException(); } @Override public void forEachRemaining(Consumer action) { Objects.requireNonNull(action); if (hasNext) { action.accept(e); hasNext = false; } } }; } private static Spliterator singletonSpliterator(final T element) { return new Spliterator() { long estimatedSize = 1; @Override public Spliterator trySplit() { return null; } @Override public boolean tryAdvance(Consumer consumer) { Objects.requireNonNull(consumer); if (estimatedSize > 0) { estimatedSize--; consumer.accept(element); return true; } return false; } @Override public void forEachRemaining(Consumer consumer) { tryAdvance(consumer); } @Override public long estimateSize() { return estimatedSize; } @Override public int characteristics() { int value = (element != null) ? Spliterator.NONNULL : 0; // ORDERED can be derived from member flag return value | Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.IMMUTABLE | Spliterator.DISTINCT | Spliterator.ORDERED; } }; } // Java 9 Stream features /** * Returns, if this stream is ordered, a stream consisting of the longest * prefix of elements taken from this stream that match the given predicate. * * @param predicate - a non-interfering, stateless predicate to apply to * elements to determine the longest prefix of elements. * @return the new stream */ public Stream takeWhile(Predicate predicate) { requireNonNull(predicate); if (predicate.test(element)) { return this; } else { return empty(); } } /** * Returns, if this stream is ordered, a stream consisting of the remaining * elements of this stream after dropping the longest prefix of elements * that match the given predicate. Otherwise returns, if this stream is * unordered, a stream consisting of the remaining elements of this stream * after dropping a subset of elements that match the given predicate. * * @param predicate - a non-interfering, stateless predicate to apply to * elements to determine the longest prefix of elements. * * @return new new stream */ public Stream dropWhile(Predicate predicate) { requireNonNull(predicate); if (predicate.test(element)) { return empty(); } else { return this; } } }