/*
* 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.
*/
/**
* This library provides enhancements for Java 8 Stream API. Public API contains the following classes and interfaces:
*
* <p>
* {@link one.util.streamex.StreamEx}: implements {@link java.util.stream.Stream}
* and provides additional functionality for object streams.
*
* <p>
* {@link one.util.streamex.IntStreamEx}, {@link one.util.streamex.LongStreamEx}, {@link one.util.streamex.DoubleStreamEx}:
* implement corresponding interfaces for primitive streams and enhancing them with additional functionality.
*
* <p>
* {@link one.util.streamex.EntryStream}: implements {@link java.util.stream.Stream} of {@link java.util.Map.Entry}
* objects providing specific methods for operate on keys or values independently.
*
* <p>
* Each of these classes contain a bunch of static methods to create the corresponding stream using different sources:
* collections, arrays, {@link java.io.Reader}, {@link java.util.Random} and so on.
*
* <p>
* {@link one.util.streamex.IntCollector}, {@link one.util.streamex.LongCollector}, {@link one.util.streamex.DoubleCollector}:
* specialized collectors to work efficiently with primitive streams.
*
* <p>
* {@link one.util.streamex.MoreCollectors}: utility class which provides a number of useful collectors
* which are absent in JDK {@link java.util.stream.Collectors} class.
*
* <p>
* {@link one.util.streamex.Joining}: an advanced implementation of joining collector.
*
* <p>
* {@link one.util.streamex.StreamEx.Emitter}, {@link one.util.streamex.IntStreamEx.IntEmitter}, {@link one.util.streamex.LongStreamEx.LongEmitter}, {@link one.util.streamex.DoubleStreamEx.DoubleEmitter}:
* helper interfaces to create custom stream sources.
*
* <h2><a name="StreamOps">Stream operations and pipelines</a></h2>
* <p>StreamEx operations are divided into <em>intermediate</em>, <em>quasi-intermediate</em> and
* <em>terminal</em> operations, and are combined to form <em>stream
* pipelines</em>. For more information about <em>intermediate</em> and <em>terminal</em> see the {@linkplain java.util.stream Stream API} documentation.
*
* <p>
* 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 {@code parallel()}
* before or after any intermediate operation. For quasi-intermediate operations if you call {@code 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 {@code sequential()}, the steps before quasi-intermediate operation may still be executed in parallel.
*
* <p>
* 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.
*
* <h3><a name="TSO">Tail stream optimization</a></h3>
*
* A few quasi-intermediate operations are tail-stream optimized (TSO) which is important when using
* {@link one.util.streamex.StreamEx#headTail(java.util.function.BiFunction) headTail}
* 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 {@code headTail} operation, and {@code 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.
*
* <h3><a name="NonInterference">Non-interference</a></h3>
*
* The function is called non-interfering if it does not modify the stream source. For more information see the {@linkplain java.util.stream Stream API} documentation.
*
* <h3><a name="Statelessness">Stateless behaviors</a></h3>
*
* 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 {@linkplain java.util.stream Stream API} documentation.
*
* <h2><a name="Reduction">Reduction operations</a></h2>
*
* <p>
* A <em>reduction</em> operation takes a sequence of input elements and combines them into a single summary result. For more information see the {@linkplain java.util.stream Stream API} documentation.
* In addition to symmetrical reduction which requires reduction function to be associative, StreamEx library provides asymmetrical reduction methods
* like {@linkplain one.util.streamex.StreamEx#foldLeft(Object, java.util.function.BiFunction) foldLeft} and {@linkplain one.util.streamex.StreamEx#foldRight(Object, java.util.function.BiFunction) 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.
*
* <h3><a name="MutableReduction">Mutable reduction</a></h3>
*
* <p>
* A <em>mutable reduction operation</em> accumulates input elements into a
* mutable result container, such as a {@code Collection},
* as it processes the elements in the stream. The mutable reduction is usually performed via {@linkplain java.util.stream.Collector collectors}.
* See the {@linkplain java.util.stream Stream API} documentation for more details.
*
* <p>
* StreamEx provides better support for mutable reduction on primitive streams. There are primitive collector classes {@link one.util.streamex.IntCollector},
* {@link one.util.streamex.LongCollector} and {@link one.util.streamex.DoubleCollector}
* which extend {@link java.util.stream.Collector} interface, but capable to process primitive streams in more efficient way compared to using the boxed stream.
*
* <p>
* Also StreamEx library defines a number of collectors absent in JDK. See {@link one.util.streamex.MoreCollectors} class.
*
* <h3><a name="ShortCircuitReduction">Short circuiting reduction</a></h3>
*
* <p>
* While Stream API has some <em>short-circuiting</em> 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 {@link java.util.stream.Stream#collect(java.util.stream.Collector) 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 <em>short-circuiting collectors</em>.
* If such special collector is passed to {@code StreamEx.collect} or {@code EntryStream.collect} terminal operation, then this operation
* becomes short-circuiting as well. If you however pass such collector to the normal {@code Stream.collect}, it will act as an ordinary
* non-short-circuiting collector. For example, this will process only one element from an input stream:
*
* <pre>
* Optional<Integer> result = IntStreamEx.range(100).boxed().collect(MoreCollectors.first());
* </pre>
*
* While this will process all the elements producing the same result:
*
* <pre>
* Optional<Integer> result = IntStream.range(0, 100).boxed().collect(MoreCollectors.first());
* </pre>
*
* <p>
* Note that when short-circuiting collector is used as the downstream, to standard JDK collectors like {@link java.util.stream.Collectors#mapping(java.util.function.Function, java.util.stream.Collector) Collectors.mapping(Function, Collector)}
* or {@link java.util.stream.Collectors#partitioningBy(java.util.function.Predicate, java.util.stream.Collector) Collectors.partitioningBy(Predicate, Collector)}, the resulting collector will not be short-circuiting.
* Instead you can use the corresponding method from {@code MoreCollectors} class.
* For example, this way you can get up to two odd and even numbers from the input stream in short-circuiting manner:
*
* <pre>
* Map<Boolean, List<Integer>> map = IntStreamEx.range(0, 100).boxed()
* .collect(MoreCollectors.partitioningBy(x -> x % 2 == 0, MoreCollectors.head(2)));
* </pre>
*
* <p>
* For some operations like {@code 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.
*
* <p>
* Currently there's no public API to create user-defined short-circuiting collectors.
* Also there are no short-circuiting collectors for primitive streams.
*
* <h3><a name="Associativity">Associativity</a></h3>
*
* An operator or function {@code op} is <em>associative</em> if the following
* holds:
* <pre>{@code
* (a op b) op c == a op (b op c)
* }</pre>
*
* For more information see the {@linkplain java.util.stream Stream API} documentation.
*
* @author Tagir Valeev
*/
package one.util.streamex;