functionalj.stream.Streamable Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of functionalj-core Show documentation
Show all versions of functionalj-core Show documentation
The module for FunctionalJ Core.
// ============================================================================
// Copyright (c) 2017-2019 Nawapunth Manusitthipol (NawaMan - http://nawaman.net).
// ----------------------------------------------------------------------------
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ============================================================================
package functionalj.stream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.concurrent.atomic.AtomicReference;
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.function.UnaryOperator;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
import functionalj.function.Func0;
import functionalj.function.Func1;
import functionalj.function.Func2;
import functionalj.functions.StrFuncs;
import functionalj.list.FuncList;
import functionalj.list.ImmutableList;
import functionalj.pipeable.Pipeable;
import functionalj.promise.UncompletedAction;
import functionalj.result.Result;
import functionalj.tuple.Tuple2;
import lombok.val;
class Helper {
static FuncList> segmentByPercentiles(FuncList list, FuncList percentiles) {
val size = list.size();
val indexes = percentiles.sorted().map(d -> (int)Math.round(d*size/100)).toArrayList();
if (indexes.get(indexes.size() - 1) != size) {
indexes.add(size);
}
val lists = new ArrayList>();
for (int i = 0; i < indexes.size(); i++) {
lists.add(new ArrayList());
}
int idx = 0;
for (int i = 0; i < size; i++) {
if (i >= indexes.get(idx)) {
idx++;
}
val l = lists.get(idx);
val element = list.get(i);
l.add(element);
}
return FuncList.from(
lists
.stream()
.map(each -> (FuncList)StreamPlus.from(each.stream()).toImmutableList()));
}
//
// static FuncList> toPercentilesOf(int size, FuncList> list) {
// val sorted
// = list
// .mapWithIndex((index, tuper) -> Tuple.of(tuper._1(), tuper._2(), index*100.0/size))
// .sortedBy(tuple -> tuple._1());
// FuncList> results = sorted
// .map(tuple -> Tuple.of(tuple._2(), tuple._3()));
// return results;
// }
}
@SuppressWarnings("javadoc")
@FunctionalInterface
public interface Streamable
extends
StreamableWithMapFirst,
StreamableWithMapThen,
StreamableWithMapTuple,
StreamableWithMapToMap,
StreamableWithSplit,
StreamableWithFillNull,
StreamableWithSegment,
StreamableWithCombine,
StreamableWithCalculate,
StreamableAddtionalOperators,
StreamableAdditionalTerminalOperators {
public static Streamable empty() {
return ()->StreamPlus.empty();
}
public static Streamable emptyStreamable() {
return ()->StreamPlus.empty();
}
@SafeVarargs
public static Streamable of(D ... data) {
return ()->StreamPlus.from(Stream.of(data));
}
@SafeVarargs
public static Streamable steamableOf(D ... data) {
return ()->StreamPlus.from(Stream.of(data));
}
public static Streamable from(Collection collection) {
return ()->StreamPlus.from(collection.stream());
}
public static Streamable from(Func0> supplier) {
return ()->StreamPlus.from(supplier.get());
}
@SafeVarargs
public static Streamable repeat(D ... data) {
return ()->StreamPlus.repeat(data);
}
public static StreamPlus repeat(FuncList data) {
return ()->StreamPlus.repeat(data);
}
@SafeVarargs
public static Streamable cycle(D ... data) {
return ()->StreamPlus.cycle(data);
}
public static StreamPlus cycle(FuncList data) {
return ()->StreamPlus.cycle(data);
}
public static Streamable loop(int time) {
return ()->StreamPlus.loop(time);
}
public static Streamable loop() {
return ()->StreamPlus.loop();
}
public static Streamable infiniteInt() {
return ()->StreamPlus.infiniteInt();
}
public static Streamable range(int startInclusive, int endExclusive) {
return ()->StreamPlus.range(startInclusive, endExclusive);
}
// Because people know this.
@SafeVarargs
public static Streamable concat(Streamable ... streams) {
return ()->StreamPlus.of(streams).flatMap(s -> s.stream());
}
// To avoid name conflict with String.concat
@SafeVarargs
public static Streamable combine(Streamable ... streams) {
return ()->StreamPlus.of(streams).flatMap(s -> s.stream());
}
public static Streamable generate(Supplier> supplier) {
return ()->StreamPlus.generate(supplier.get());
}
public static Streamable generateWith(Supplier> supplier) {
return ()->StreamPlus.generate(supplier.get());
}
public static Streamable iterate(D seed, UnaryOperator f) {
return ()->StreamPlus.iterate(seed, f);
}
public static Streamable compound(D seed, UnaryOperator f) {
return ()->StreamPlus.compound(seed, f);
}
public static Streamable iterate(D seed1, D seed2, BinaryOperator f) {
return ()->StreamPlus.iterate(seed1, seed2, f);
}
public static Streamable compound(D seed1, D seed2, BinaryOperator f) {
return ()->StreamPlus.compound(seed1, seed2, f);
}
public static Streamable> zipOf(
Streamable stream1,
Streamable stream2) {
return ()->{
return StreamPlus.zipOf(
stream1.stream(),
stream2.stream());
};
}
public static Streamable zipOf(
Streamable stream1,
Streamable stream2,
Func2 merger) {
return ()->{
return StreamPlus.zipOf(
stream1.stream(),
stream2.stream(),
merger);
};
}
public static Streamable with(
Streamable source,
Function, Stream> action) {
return new Streamable() {
@Override
public StreamPlus stream() {
val sourceStream = source.stream();
val targetStream = action.apply(sourceStream);
return StreamPlus.from(targetStream);
}
};
}
public static Streamable from(
Streamable source,
Function, Stream> action) {
return new Streamable() {
@Override
public StreamPlus stream() {
val targetStream = action.apply(source);
return StreamPlus.from(targetStream);
}
};
}
//== Stream ==
public StreamPlus stream();
//== Helper functions ==
public default Streamable deriveWith(Function, Stream> action) {
return Streamable.with(this, action);
}
public default Streamable deriveFrom(Function, Stream> action) {
return Streamable.from(this, action);
}
//== Stream sepecific ==
public default Streamable sequential() {
return deriveWith(stream -> {
return stream.sequential();
});
}
public default Streamable parallel() {
return deriveWith(stream -> {
return stream.parallel();
});
}
public default Streamable unordered() {
return deriveWith(stream -> {
return stream.unordered();
});
}
//== Functionalities ==
public default IntStreamPlus mapToInt(ToIntFunction super DATA> mapper) {
return IntStreamPlus.from(stream().mapToInt(mapper));
}
public default LongStreamPlus mapToLong(ToLongFunction super DATA> mapper) {
return stream().mapToLong(mapper);
}
public default DoubleStreamPlus mapToDouble(ToDoubleFunction super DATA> mapper) {
return stream().mapToDouble(mapper);
}
public default IntStreamPlus flatMapToInt(Function super DATA, ? extends IntStream> mapper) {
return IntStreamPlus.from(stream().flatMapToInt(mapper));
}
public default LongStreamPlus flatMapToLong(Function super DATA, ? extends LongStream> mapper) {
return stream().flatMapToLong(mapper);
}
public default DoubleStreamPlus flatMapToDouble(Function super DATA, ? extends DoubleStream> mapper) {
return stream().flatMapToDouble(mapper);
}
public default Streamable map(Function super DATA, ? extends TARGET> mapper) {
return deriveWith(stream -> {
return stream.map(mapper);
});
}
public default Streamable flatMap(Function super DATA, ? extends Streamable extends TARGET>> mapper) {
return deriveWith(stream -> {
return stream.flatMap(e -> mapper.apply(e).stream());
});
}
public default Streamable filter(Predicate super DATA> predicate) {
return deriveWith(stream -> {
return (predicate == null)
? stream
: stream.filter(predicate);
});
}
public default Streamable peek(Consumer super DATA> action) {
return deriveWith(stream -> {
return (action == null)
? stream
: stream.peek(action);
});
}
//-- Limit/Skip --
public default Streamable limit(long maxSize) {
return deriveWith(stream -> {
return stream.limit(maxSize);
});
}
public default Streamable skip(long n) {
return deriveWith(stream -> {
return stream.skip(n);
});
}
public default Streamable limit(Long maxSize) {
return deriveWith(stream -> {
return ((maxSize == null) || (maxSize.longValue() < 0))
? stream
: stream.limit(maxSize);
});
}
public default Streamable skip(Long startAt) {
return deriveWith(stream -> {
return ((startAt == null) || (startAt.longValue() < 0))
? stream
: stream.skip(startAt);
});
}
public default Streamable skipWhile(Predicate super DATA> condition) {
return deriveWith(stream -> {
return StreamPlus.from(stream).skipWhile(condition);
});
}
public default Streamable skipUntil(Predicate super DATA> condition) {
return deriveWith(stream -> {
return StreamPlus.from(stream).skipUntil(condition);
});
}
public default Streamable takeWhile(Predicate super DATA> condition) {
return deriveWith(stream -> {
return StreamPlus.from(stream).takeWhile(condition);
});
}
public default Streamable takeUntil(Predicate super DATA> condition) {
return deriveWith(stream -> {
return StreamPlus.from(stream).takeUntil(condition);
});
}
public default Streamable distinct() {
return deriveWith(stream -> {
return stream.distinct();
});
}
//-- Sorted --
public default Streamable sorted() {
return deriveWith(stream -> {
return stream.sorted();
});
}
public default Streamable sorted(
Comparator super DATA> comparator) {
return deriveWith(stream -> {
return (comparator == null)
? stream.sorted()
: stream.sorted(comparator);
});
}
public default > Streamable sortedBy(
Function super DATA, T> mapper) {
return deriveWith(stream -> {
return stream.sorted((a, b) -> {
T vA = mapper.apply(a);
T vB = mapper.apply(b);
return vA.compareTo(vB);
});
});
}
public default Streamable sortedBy(
Function super DATA, T> mapper,
Comparator comparator) {
return deriveWith(stream -> {
return stream.sorted((a, b) -> {
T vA = mapper.apply(a);
T vB = mapper.apply(b);
return Objects.compare(vA, vB, comparator);
});
});
}
//-- Terminate --
public default void forEach(Consumer super DATA> action) {
if (action == null)
return;
stream().forEach(action);
}
public default void forEachOrdered(Consumer super DATA> action) {
if (action == null)
return;
stream().forEachOrdered(action);
}
public default DATA reduce(DATA identity, BinaryOperator accumulator) {
return stream().reduce(identity, accumulator);
}
public default Optional reduce(BinaryOperator accumulator) {
return stream().reduce(accumulator);
}
public default U reduce(
U identity,
BiFunction accumulator,
BinaryOperator combiner) {
return stream().reduce(identity, accumulator, combiner);
}
public default R collect(
Collector super DATA, A, R> collector) {
return stream().collect(collector);
}
public default R collect(
Supplier supplier,
BiConsumer accumulator,
BiConsumer combiner) {
return stream().collect(supplier, accumulator, combiner);
}
public default Optional min(
Comparator super DATA> comparator) {
return stream().min(comparator);
}
public default Optional max(
Comparator super DATA> comparator) {
return stream().max(comparator);
}
public default long count() {
return stream().count();
}
public default int size() {
return (int)stream().count();
}
public default boolean anyMatch(
Predicate super DATA> predicate) {
return stream().anyMatch(predicate);
}
public default boolean allMatch(
Predicate super DATA> predicate) {
return stream().allMatch(predicate);
}
public default boolean noneMatch(
Predicate super DATA> predicate) {
return stream().noneMatch(predicate);
}
public default Optional findFirst() {
return stream().findFirst();
}
public default Optional findAny() {
return stream().findAny();
}
//== toXXX ===
public default Object[] toArray() {
return stream().toArray();
}
public default T[] toArray(T[] a) {
return StreamPlus.of(stream()).toJavaList().toArray(a);
}
public default A[] toArray(IntFunction generator) {
return stream().toArray(generator);
}
public default List toJavaList() {
return stream().collect(Collectors.toList());
}
public default byte[] toByteArray(Func1 toByte) {
val byteArray = new ByteArrayOutputStream();
stream().forEach(d -> byteArray.write(toByte.apply(d)));
return byteArray.toByteArray();
}
public default int[] toIntArray(ToIntFunction toInt) {
return mapToInt(toInt).toArray();
}
public default long[] toLongArray(ToLongFunction toLong) {
return mapToLong(toLong).toArray();
}
public default double[] toDoubleArray(ToDoubleFunction toDouble) {
return mapToDouble(toDouble).toArray();
}
public default FuncList toList() {
return toImmutableList();
}
public default FuncList toLazyList() {
return FuncList.from(this);
}
public default String toListString() {
return "[" + map(String::valueOf).collect(Collectors.joining(", ")) + "]";
}
public default ImmutableList toImmutableList() {
return ImmutableList.from(stream());
}
public default List toMutableList() {
return toArrayList();
}
public default ArrayList toArrayList() {
return new ArrayList(toJavaList());
}
public default Set toSet() {
return new HashSet(stream().collect(Collectors.toSet()));
}
//-- Iterator --
public default IteratorPlus iterator() {
return IteratorPlus.from(stream());
}
public default Spliterator spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
//== Plus ==
public default String joinToString() {
return map(StrFuncs::toStr)
.collect(Collectors.joining());
}
public default String joinToString(String delimiter) {
return map(StrFuncs::toStr)
.collect(Collectors.joining(delimiter));
}
//++ Plus w/ Self ++
public default Pipeable> pipable() {
return Pipeable.of(this);
}
public default T pipe(Function super Streamable, T> piper) {
return piper.apply(this);
}
//== Spawn ==
public default Streamable> spawn(Func1> mapper) {
return deriveWith(stream -> {
return StreamPlus.from(stream()).spawn(mapper);
});
}
//== accumulate + restate ==
public default Streamable accumulate(BiFunction super DATA, ? super DATA, ? extends DATA> accumulator) {
return deriveWith(stream -> {
val iterator = StreamPlus.from(stream).iterator();
if (!iterator.hasNext())
return StreamPlus.empty();
val prev = new AtomicReference(iterator.next());
return StreamPlus.concat(
StreamPlus.of(prev.get()),
iterator.stream().map(n -> {
val next = accumulator.apply(n, prev.get());
prev.set(next);
return next;
})
);
});
}
public default Streamable restate(BiFunction super DATA, Streamable, Streamable> restater) {
val func = (UnaryOperator>>)((Tuple2> pair) -> {
val stream = pair._2();
val iterator = stream.iterator();
if (!iterator.hasNext())
return null;
val head = iterator.next();
val tail =restater.apply(head, ()->iterator.stream());
return Tuple2.of(head, tail);
});
val seed = Tuple2.of((DATA)null, this);
val endStream = (Streamable)(()->StreamPlus.iterate(seed, func).takeUntil(t -> t == null).skip(1).map(t -> t._1()));
return endStream;
}
//
// public default > FuncList> toPercentilesOf(Function super DATA, T> mapper) {
// FuncList> list
// = mapWithIndex(Tuple2::of)
// .sortedBy(tuple -> mapper.apply(tuple._2()))
// .toImmutableList();
// return Helper.toPercentilesOf(size() - 1, list);
// }
//
// public default FuncList> toPercentilesOf(Function super DATA, T> mapper, Comparator comparator) {
// FuncList> list
// = mapWithIndex(Tuple2::of)
// .sortedBy(tuple -> mapper.apply(tuple._2()), comparator)
// .toImmutableList();
// return Helper.toPercentilesOf(size() - 1, list);
// }
}