one.util.streamex.BaseStreamEx Maven / Gradle / Ivy
/*
* 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 super B, U> mapper);
}