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

com.speedment.common.singletonstream.SingletonIntStream 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 static com.speedment.common.singletonstream.internal.SingletonUtil.TRIPWIRE_ENABLED;
import static com.speedment.common.singletonstream.internal.SingletonUtil.trip;
import java.util.IntSummaryStatistics;
import java.util.NoSuchElementException;
import java.util.Objects;
import static java.util.Objects.requireNonNull;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.PrimitiveIterator;
import java.util.Spliterator;
import java.util.function.BiConsumer;
import java.util.function.IntBinaryOperator;
import java.util.function.IntConsumer;
import java.util.function.IntFunction;
import java.util.function.IntPredicate;
import java.util.function.IntToDoubleFunction;
import java.util.function.IntToLongFunction;
import java.util.function.IntUnaryOperator;
import java.util.function.ObjIntConsumer;
import java.util.function.Supplier;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;

/**
 * An implementation of an IntStream that takes exactly one element as its
 * source.
 *
 * This implementation supports optimized implementations of most terminal
 * operations and a some number of intermediate operations. Un-optimized
 * operations just returns a wrapped standard IntStream implementation.
 *
 * For performance reasons, the IntStream 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
 * @since  1.0.0
 */
public class SingletonIntStream implements IntStream {

    private final int element;

    private SingletonIntStream(int element) {
        this.element = element;
    }

    public static IntStream of(int element) {
        return new SingletonIntStream(element);
    }

    @Override
    public IntStream filter(IntPredicate predicate) {
        requireNonNull(predicate);
        if (STRICT) {
            return toStream().filter(predicate);
        }
        return predicate.test(element) ? this : empty();
    }

    @Override
    public IntStream map(IntUnaryOperator mapper) {
        requireNonNull(mapper);
        if (STRICT) {
            return toStream().map(mapper);
        }
        return of(mapper.applyAsInt(element));
    }

    @Override
    public  Stream mapToObj(IntFunction mapper) {
        requireNonNull(mapper);
        if (STRICT) {
            return toStream().mapToObj(mapper);
        }
        return SingletonStream.of(mapper.apply(element));
    }

    @Override
    public LongStream mapToLong(IntToLongFunction mapper) {
        requireNonNull(mapper);
        if (STRICT) {
            return toStream().mapToLong(mapper);
        }
        return SingletonLongStream.of(mapper.applyAsLong(element));
    }

    @Override
    public DoubleStream mapToDouble(IntToDoubleFunction mapper) {
        requireNonNull(mapper);
        if (STRICT) {
            return toStream().mapToDouble(mapper);
        }
        return DoubleStream.of(mapper.applyAsDouble(element));
    }

    @Override
    public IntStream flatMap(IntFunction mapper) {
        requireNonNull(mapper);
        if (STRICT) {
            return toStream().flatMap(mapper);
        }
        return mapper.apply(element);
    }

    @Override
    public IntStream distinct() {
        return this;
    }

    @Override
    public IntStream sorted() {
        return this;
    }

    @Override
    public IntStream peek(IntConsumer action) {
        requireNonNull(action);
        return toStream().peek(action);
    }

    @Override
    public IntStream limit(long maxSize) {
        if (maxSize == 0) {
            return empty();
        }
        if (maxSize > 0) {
            return this;
        }
        throw new IllegalArgumentException(Long.toString(maxSize));
    }

    @Override
    public IntStream skip(long n) {
        if (n == 0) {
            return this;
        }
        if (n > 0) {
            return empty();
        }
        throw new IllegalArgumentException(Long.toString(n));
    }

    @Override
    public void forEach(IntConsumer action) {
        requireNonNull(action);
        action.accept(element);
    }

    @Override
    public void forEachOrdered(IntConsumer action) {
        requireNonNull(action);
        action.accept(element);
    }

    @Override
    public int[] toArray() {
        final int[] result = new int[1];
        result[0] = element;
        return result;
    }

    @Override
    public int reduce(int identity, IntBinaryOperator op) {
        requireNonNull(op);
        return op.applyAsInt(identity, element);
    }

    @Override
    public OptionalInt reduce(IntBinaryOperator op) {
        // Just one element so the accumulator is never called.
        return toOptional();
    }

    @Override
    public  R collect(Supplier supplier, ObjIntConsumer 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 int sum() {
        return element;
    }

    @Override
    public OptionalInt min() {
        return toOptional();
    }

    @Override
    public OptionalInt max() {
        return toOptional();
    }

    @Override
    public long count() {
        return 1;
    }

    @Override
    public OptionalDouble average() {
        return OptionalDouble.of(element);
    }

    @Override
    public IntSummaryStatistics summaryStatistics() {
        final IntSummaryStatistics result = new IntSummaryStatistics();
        result.accept(element);
        return result;
    }

    @Override
    public boolean anyMatch(IntPredicate predicate) {
        requireNonNull(predicate);
        return predicate.test(element);
    }

    @Override
    public boolean allMatch(IntPredicate predicate) {
        requireNonNull(predicate);
        return predicate.test(element);
    }

    @Override
    public boolean noneMatch(IntPredicate predicate) {
        requireNonNull(predicate);
        return !predicate.test(element);
    }

    @Override
    public OptionalInt findFirst() {
        return toOptional();
    }

    @Override
    public OptionalInt findAny() {
        return toOptional();
    }

    @Override
    public LongStream asLongStream() {
        return LongStream.of(element);
    }

    @Override
    public DoubleStream asDoubleStream() {
        return DoubleStream.of(element);
    }

    @Override
    public Stream boxed() {
        return mapToObj(Integer::valueOf);
    }

    @Override
    public IntStream sequential() {
        return this;
    }

    @Override
    public IntStream parallel() {
        return toStream().parallel();
    }

    @Override
    public PrimitiveIterator.OfInt iterator() {
        return singletonIntIterator(element);
    }

    @Override
    public Spliterator.OfInt spliterator() {
        return singletonIntSpliterator(element);
    }

    @Override
    public boolean isParallel() {
        return false;
    }

    @Override
    public IntStream unordered() {
        return this; // Todo: may convey to singletonSpliterator()
    }

    @Override
    public IntStream onClose(Runnable closeHandler) {
        return toStream().onClose(closeHandler);
    }

    @Override
    public void close() {
       // do nothing. OnClose createa a real Stream
    }

    private IntStream toStream() {
        return IntStream.of(element);
    }

    private OptionalInt toOptional() {
        // if element is null, Optional will throw an NPE 
        // just as the standard Stream implementation does.
        return OptionalInt.of(element);
    }

    private static IntStream empty() {
        return IntStream.empty();
    }

    private static PrimitiveIterator.OfInt singletonIntIterator(final int e) {
        return new PrimitiveIterator.OfInt() {
            private boolean hasNext = true;

            @Override
            public boolean hasNext() {
                return hasNext;
            }

            @Override
            public int nextInt() {
                if (hasNext) {
                    hasNext = false;
                    return e;
                }
                throw new NoSuchElementException();
            }

            @Override
            public Integer next() {
                if (TRIPWIRE_ENABLED) {
                    trip(getClass(), "{0} calling SingletonIntStream.singletonIterator.next()");
                }
                if (!hasNext) {
                    throw new NoSuchElementException();
                }
                return nextInt();
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException();
            }

            @Override
            public void forEachRemaining(IntConsumer action) {
                requireNonNull(action);
                if (hasNext) {
                    action.accept(e);
                    hasNext = false;
                }
            }
        };
    }

    private static Spliterator.OfInt singletonIntSpliterator(final int element) {
        return new Spliterator.OfInt() {
            long estimatedSize = 1;

            @Override
            public Spliterator.OfInt trySplit() {
                return null;
            }

            @Override
            public boolean tryAdvance(IntConsumer consumer) {
                Objects.requireNonNull(consumer);
                if (estimatedSize > 0) {
                    estimatedSize--;
                    consumer.accept(element);
                    return true;
                }
                return false;
            }

            @Override
            public void forEachRemaining(IntConsumer consumer) {
                tryAdvance(consumer);
            }

            @Override
            public long estimateSize() {
                return estimatedSize;
            }

            @Override
            public int characteristics() {
                return Spliterator.NONNULL | 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 IntStream takeWhile(IntPredicate 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 IntStream dropWhile(IntPredicate predicate) {
        requireNonNull(predicate);
        if (predicate.test(element)) {
            return empty();
        } else {
            return this;
        }
    }

}