package org.infinispan.commons.api.functional; import java.util.Comparator; import java.util.Optional; 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.Predicate; import java.util.function.Supplier; import java.util.stream.Collector; import org.infinispan.commons.util.Experimental; /** * Unsorted traversable stream for sequential and aggregating operations. * * <p>Traversable contains two type of operations: * <ol> * <li>Intermediate operations which transform a traversable, into another, * e.g. {@link #filter(Predicate)}. * </li> * <li>Terminal operations which produce a side effect, e.g. {@link #forEach(Consumer)}. * Once a terminal operation is completed, the resources taken by the * traversable are released. * </li> * </ol> * * <p>Traversable cannot be reused and hence is designed to be used only once * via its intermediate and terminal operations. * * <p>In distributed environments, unless individually specified, all lambdas * passed to methods are executed where data is located. For example, if * executing {@link #forEach(Consumer)}, the {@link Consumer} function is * executed wherever a particular key resides. To execute a for-each operation * where the side effects are executed locally, all the {@link Traversable}'s * data needs to be collected and iterated over manually. * * @param <T> * @since 8.0 */ @Experimental public interface Traversable<T> { /** * An intermediate operation that returns a traversable containing elements * matching the given predicate. */ Traversable<T> filter(Predicate<? super T> p); /** * An intermediate operation that returns a traversable containing the * results of applying the given function over the elements of the * traversable. */ <R> Traversable<R> map(Function<? super T, ? extends R> f); /** * An intermediate operation that returns a traversable containing the * results of replacing each element of this traversable with the contents * of a traversable produced by applying the provided function to each element. * * <p>From a functional map perspective, this operation is particularly handy * when the values are collections. */ <R> Traversable<R> flatMap(Function<? super T, ? extends Traversable<? extends R>> f); /** * A terminal operation that applies an operation to all elements of this * traversable. */ void forEach(Consumer<? super T> c); /** * A terminal operation that applies a binary folding operation to a start * value and all elements of this traversable. */ T reduce(T z, BinaryOperator<T> folder); /** * A terminal operation that applies a binary folding operation to all * elements of this traversable, and wraps the result in an optional. * If the traversable is empty, it returns an empty optional. */ Optional<T> reduce(BinaryOperator<T> folder); /** * A terminal operation that applies a binary folding operation to a start * value and the result of each element having a mapping function applied. * * <p>This is a combined map/reduce which could potentially be done more * efficiently than if a map is executed and then reduce. */ <U> U reduce(U z, BiFunction<U, ? super T, U> mapper, BinaryOperator<U> folder); /** * A terminal operation that transforms the traversable into a result * container, first constructed with the given supplier, and then * accumulating elements over it with the given consumer. * * <p>The combiner can be used to combine accumulated results executed in * parallel or coming from different nodes in a distributed environment. * * <p>In distributed environments where some keys are remote, the * {@link Supplier} and {@link BiConsumer} instances passed in are sent to * other nodes and hence they need to be marshallable. If the collect * operation can be defined using the helper methods in * {@link java.util.stream.Collectors}, it is recommended that those are * used, which can easily be made marshalled using the * {@code org.infinispan.stream.CacheCollectors#serializableCollector} method. */ <R> R collect(Supplier<R> s, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner); /** * A terminal operation that transforms the traversable into a result * container using a {@code Collector}. * * <p>In distributed environments where some keys are remote, the * {@link Collector} instance passed in is sent other nodes and hence it * needs to be marshallable. This can easily be made achieved using the * {@code org.infinispan.stream.CacheCollectors#serializableCollector} method. */ <R, A> R collect(Collector<? super T, A, R> collector); /** * A terminal operation that returns an optional containing the minimum * element of this traversable based on the comparator passed in. * If the traversable is empty, it returns an empty optional. */ default Optional<T> min(Comparator<? super T> comparator) { return reduce(BinaryOperator.minBy(comparator)); } /** * A terminal operation that returns an optional containing the maximum * element of this traversable based on the comparator passed in. * If the traversable is empty, it returns an empty optional. */ default Optional<T> max(Comparator<? super T> comparator) { return reduce(BinaryOperator.maxBy(comparator)); } /** * A terminal operation that returns the number of elements in the traversable. */ long count(); /** * A terminal operation that returns whether any elements of this * traversable match the provided predicate. * * <p>An important reason to keep this method is the fact as opposed * to a reduction which must evaluate all elements in the traversable, this * method could stop as soon as it has found an element that matches. */ boolean anyMatch(Predicate<? super T> p); /** * A terminal operation that returns whether all elements of this * traversable match the provided predicate. * * <p>An important reason to keep this method is the fact as opposed * to a reduction which must evaluate all elements in the traversable, this * method could stop as soon as it has found an element that does not match * the predicate. */ boolean allMatch(Predicate<? super T> p); /** * A terminal operation that returns whether no elements of this * traversable match the provided predicate. * * <p>An important reason to keep this method is the fact as opposed * to a reduction which must evaluate all elements in the traversable, this * method could stop as soon as it has found an element that does matches * the predicate. */ boolean noneMatch(Predicate<? super T> predicate); /** * A terminal operation that returns an optional containing an element of * the traversable, or an empty optional if empty. */ Optional<T> findAny(); }