Package one.util.streamex
StreamEx
: implements Stream
and provides additional functionality for object streams.
IntStreamEx
, LongStreamEx
, DoubleStreamEx
:
implement corresponding interfaces for primitive streams and enhancing them with additional functionality.
EntryStream
: implements Stream
of Map.Entry
objects providing specific methods for operate on keys or values independently.
Each of these classes contain a bunch of static methods to create the corresponding stream using different sources:
collections, arrays, Reader
, Random
and so on.
IntCollector
, LongCollector
, DoubleCollector
:
specialized collectors to work efficiently with primitive streams.
MoreCollectors
: utility class which provides a number of useful collectors
which are absent in JDK Collectors
class.
Joining
: an advanced implementation of joining collector.
StreamEx.Emitter
, IntStreamEx.IntEmitter
, LongStreamEx.LongEmitter
, DoubleStreamEx.DoubleEmitter
:
helper interfaces to create custom stream sources.
Stream operations and pipelines
StreamEx operations are divided into intermediate, quasi-intermediate and terminal operations, and are combined to form stream pipelines. For more information about intermediate and terminal see the Stream API documentation.
In addition, due to the API limitations, a new operation type is defined in StreamEx library which is called "quasi-intermediate".
In most of the cases they behave as intermediate operations: for sequential stream there
should be no visible difference between intermediate and quasi-intermediate operation. The only known difference
is when handling a parallel and unordered stream status. For intermediate operation there's no difference on calling parallel()
before or after any intermediate operation. For quasi-intermediate operations if you call parallel()
after the operation, then previous
steps will remain sequential. Similarly if you create a parallel stream, perform some intermediate operations, use quasi-intermediate operation,
then call sequential()
, the steps before quasi-intermediate operation may still be executed in parallel.
Also the difference appears if you have an ordered stream source, but an unordered terminal operation (or collect using the unordered collector). If you have only intermediate operations in-between, then all of them will be performed as unordered. However if you have a quasi-intermediate operation, then unordered mode is not propagated through it, so the operations prior to the quasi-intermediate operation (including the quasi-intermediate operation itself) will remain ordered.
Tail stream optimization
A few quasi-intermediate operations are tail-stream optimized (TSO) which is important when usingheadTail
method recursively. When the TSO-compatible operation understands that it should just pass-through
the rest of the stream as-is, it notifies the surrounding headTail
operation, and headTail
operation
removes the TSO-compatible operation from the pipeline shortening the call stack.
This allows writing many recursively defined operations which consume constant amount of the call stack and the heap.
Non-interference
The function is called non-interfering if it does not modify the stream source. For more information see the Stream API documentation.Stateless behaviors
The function is called stateless if its result does not depend on any state which may be changed during the stream execution. For more information see the Stream API documentation.Reduction operations
A reduction operation takes a sequence of input elements and combines them into a single summary result. For more information see the Stream API documentation. In addition to symmetrical reduction which requires reduction function to be associative, StreamEx library provides asymmetrical reduction methods like foldLeft and foldRight. These methods can be safely used for parallel streams, but the absence of associativity may lead to the performance drawback. Use them only if you cannot provide an associative reduction function.
Mutable reduction
A mutable reduction operation accumulates input elements into a
mutable result container, such as a Collection
,
as it processes the elements in the stream. The mutable reduction is usually performed via collectors.
See the Stream API documentation for more details.
StreamEx provides better support for mutable reduction on primitive streams. There are primitive collector classes IntCollector
,
LongCollector
and DoubleCollector
which extend Collector
interface, but capable to process primitive streams in more efficient way compared to using the boxed stream.
Also StreamEx library defines a number of collectors absent in JDK. See MoreCollectors
class.
Short circuiting reduction
While Stream API has some short-circuiting operations which may process only some of input elements (in particular may allow to process an infinite stream in finite time),
a mutable reduction via Stream.collect(Collector)
is always non short-circuiting.
This method is extended in StreamEx library. A new type of collectors is introduced which is called short-circuiting collectors.
If such special collector is passed to StreamEx.collect
or EntryStream.collect
terminal operation, then this operation
becomes short-circuiting as well. If you however pass such collector to the normal Stream.collect
, it will act as an ordinary
non-short-circuiting collector. For example, this will process only one element from an input stream:
Optional<Integer> result = IntStreamEx.range(100).boxed().collect(MoreCollectors.first());While this will process all the elements producing the same result:
Optional<Integer> result = IntStream.range(0, 100).boxed().collect(MoreCollectors.first());
Note that when short-circuiting collector is used as the downstream, to standard JDK collectors like Collectors.mapping(Function, Collector)
or Collectors.partitioningBy(Predicate, Collector)
, the resulting collector will not be short-circuiting.
Instead you can use the corresponding method from MoreCollectors
class.
For example, this way you can get up to two odd and even numbers from the input stream in short-circuiting manner:
Map<Boolean, List<Integer>> map = IntStreamEx.range(0, 100).boxed() .collect(MoreCollectors.partitioningBy(x -> x % 2 == 0, MoreCollectors.head(2)));
For some operations like groupingBy
it's impossible to create a short-circuiting collector even if the downstream is short-circuiting, because it's not known whether
all the possible groups are already created.
Currently there's no public API to create user-defined short-circuiting collectors. Also there are no short-circuiting collectors for primitive streams.
Associativity
An operator or functionop
is associative if the following
holds:
(a op b) op c == a op (b op c)
For more information see the Stream API documentation.- Author:
- Tagir Valeev
-
Interface Summary Interface Description DoubleCollector<A,R> ACollector
specialized to work with primitivedouble
.DoubleStreamEx.DoubleEmitter A helper interface to build a new stream by emitting elements and creating new emitters in a chain.IntCollector<A,R> ACollector
specialized to work with primitiveint
.IntStreamEx.IntEmitter A helper interface to build a new stream by emitting elements and creating new emitters in a chain.LongCollector<A,R> ACollector
specialized to work with primitivelong
.LongStreamEx.LongEmitter A helper interface to build a new stream by emitting elements and creating new emitters in a chain.StreamEx.Emitter<T> A helper interface to build a new stream by emitting elements and creating new emitters in a chain. -
Class Summary Class Description AbstractStreamEx<T,S extends AbstractStreamEx<T,S>> Base class providing common functionality forStreamEx
andEntryStream
.DoubleStreamEx ADoubleStream
implementation with additional functionalityEntryStream<K,V> IntStreamEx AnIntStream
implementation with additional functionalityJoining An advanced implementation of joiningCollector
.LongStreamEx ALongStream
implementation with additional functionalityMoreCollectors Implementations of several collectors in addition to ones available in JDK.StreamEx<T> AStream
implementation with additional functionality.