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

one.util.streamex.BaseStreamEx Maven / Gradle / Ivy

There is a newer version: 0.8.3
Show newest version
/*
 * Copyright 2015, 2016 Tagir Valeev
 * 
 * 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 one.util.streamex;

import java.util.Spliterator;
import java.util.concurrent.ForkJoinPool;
import java.util.function.Function;
import java.util.stream.BaseStream;

/**
 * @author Tagir Valeev
 */
/* package */abstract class BaseStreamEx, SPLTR extends Spliterator, B extends BaseStreamEx>
        implements BaseStream {
    static final String CONSUMED_MESSAGE = "Stream is already consumed";

    private S stream;
    SPLTR spliterator;
    StreamContext context;

    BaseStreamEx(S stream, StreamContext context) {
        this.stream = stream;
        this.context = context;
    }

    BaseStreamEx(SPLTR spliterator, StreamContext context) {
        this.spliterator = spliterator;
        this.context = context;
    }

    abstract S createStream();

    final S stream() {
        if (stream != null)
            return stream;
        if (spliterator == null)
            throw new IllegalStateException(CONSUMED_MESSAGE);
        stream = createStream();
        spliterator = null;
        return stream;
    }

    @SuppressWarnings("unchecked")
    @Override
    public SPLTR spliterator() {
        if (stream != null)
            return (SPLTR) stream.spliterator();
        if (spliterator != null) {
            SPLTR s = spliterator;
            spliterator = null;
            return s;
        }
        throw new IllegalStateException(CONSUMED_MESSAGE);
    }

    @Override
    public boolean isParallel() {
        return context.parallel;
    }

    @SuppressWarnings("unchecked")
    @Override
    public S sequential() {
        context = context.sequential();
        if (stream != null)
            stream = stream.sequential();
        return (S) this;
    }

    /**
     * {@inheritDoc}
     * 
     * 

* If this stream was created using {@link #parallel(ForkJoinPool)}, the new * stream forgets about supplied custom {@link ForkJoinPool} and its * terminal operation will be executed in common pool. */ @SuppressWarnings("unchecked") @Override public S parallel() { context = context.parallel(); if (stream != null) stream = stream.parallel(); return (S) this; } /** * Returns an equivalent stream that is parallel and bound to the supplied * {@link ForkJoinPool}. * *

* This is an intermediate * operation. * *

* The terminal operation of this stream or any derived stream (except the * streams created via {@link #parallel()} or {@link #sequential()} methods) * will be executed inside the supplied {@code ForkJoinPool}. If current * thread does not belong to that pool, it will wait till calculation * finishes. * * @param fjp a {@code ForkJoinPool} to submit the stream operation to. * @return a parallel stream bound to the supplied {@code ForkJoinPool} * @since 0.2.0 */ @SuppressWarnings("unchecked") public S parallel(ForkJoinPool fjp) { context = context.parallel(fjp); if (stream != null) stream = stream.parallel(); return (S) this; } @SuppressWarnings("unchecked") @Override public S unordered() { stream = stream().unordered(); return (S) this; } @SuppressWarnings("unchecked") @Override public S onClose(Runnable closeHandler) { context = context.onClose(closeHandler); return (S) this; } @Override public void close() { context.close(); } /** * Applies the supplied function to this stream and returns the result of * the function. * *

* This method can be used to add more functionality in the fluent style. * For example, consider user-defined static method * {@code batches(stream, n)} which breaks the stream into batches of given * length. Normally you would write * {@code batches(StreamEx.of(input).map(...), 10).filter(...)}. Using the * {@code chain()} method you can write in more fluent manner: * {@code StreamEx.of(input).map(...).chain(s -> batches(s, 10)).filter(...)}. * *

* You could even go further and define a method which returns a function * like {@code UnaryOperator> batches(int n)} and use it * like this: * {@code StreamEx.of(input).map(...).chain(batches(10)).filter(...)}. * * @param the type of the function result. * @param mapper function to invoke. * @return the result of the function invocation. * @since 0.5.4 */ abstract public U chain(Function mapper); }