content: /*
   * Copyright 2015, 2024 StreamEx contributors
   *
   * 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 id="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 id="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 id="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 id="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 id="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 id="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 id="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&lt;Integer&gt; result = IntStreamEx.range(100).boxed().collect(MoreCollectors.first());
   * </pre>
   * 
   * While this will process all the elements producing the same result:
   * 
   * <pre>
   * Optional&lt;Integer&gt; 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&lt;Boolean, List&lt;Integer&gt;&gt; map = IntStreamEx.range(0, 100).boxed()
   *                .collect(MoreCollectors.partitioningBy(x -&gt; 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 id="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;
  
  