All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.landawn.abacus.util.stream.EntryStream Maven / Gradle / Ivy

Go to download

A general programming library in Java/Android. It's easy to learn and simple to use with concise and powerful APIs.

The newest version!
/*
 * Copyright (C) 2016, 2017, 2018, 2019 HaiYang Li
 *
 * 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
 *
 * https://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.
 */

package com.landawn.abacus.util.stream;

import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.BinaryOperator;
import java.util.function.BooleanSupplier;
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.stream.Collector;

import com.landawn.abacus.annotation.Beta;
import com.landawn.abacus.annotation.IntermediateOp;
import com.landawn.abacus.annotation.LazyEvaluation;
import com.landawn.abacus.annotation.ParallelSupported;
import com.landawn.abacus.annotation.SequentialOnly;
import com.landawn.abacus.annotation.TerminalOp;
import com.landawn.abacus.annotation.TerminalOpTriggered;
import com.landawn.abacus.exception.TooManyElementsException;
import com.landawn.abacus.util.AsyncExecutor;
import com.landawn.abacus.util.BiIterator;
import com.landawn.abacus.util.Comparators;
import com.landawn.abacus.util.Difference;
import com.landawn.abacus.util.Duration;
import com.landawn.abacus.util.Fn;
import com.landawn.abacus.util.If.OrElse;
import com.landawn.abacus.util.ImmutableMap;
import com.landawn.abacus.util.Indexed;
import com.landawn.abacus.util.IntList;
import com.landawn.abacus.util.Iterables;
import com.landawn.abacus.util.Joiner;
import com.landawn.abacus.util.ListMultimap;
import com.landawn.abacus.util.MergeResult;
import com.landawn.abacus.util.Multimap;
import com.landawn.abacus.util.Multiset;
import com.landawn.abacus.util.N;
import com.landawn.abacus.util.NoCachingNoUpdating.DisposableEntry;
import com.landawn.abacus.util.ObjIterator;
import com.landawn.abacus.util.Pair;
import com.landawn.abacus.util.Percentage;
import com.landawn.abacus.util.RateLimiter;
import com.landawn.abacus.util.Throwables;
import com.landawn.abacus.util.cs;
import com.landawn.abacus.util.u.Optional;

/**
 * Note: This class includes codes copied from StreamEx: StreamEx under Apache License, version 2.0.
 * 
* * The EntryStream class represents a stream of Map.Entry elements and supports different kinds of computations. * The Stream operations are divided into intermediate and terminal operations, and are combined to form stream pipelines. * *
* The Stream will be automatically closed after a terminal method is called/triggered. *
*
* Refer to {@code com.landawn.abacus.util.stream.BaseStream} and {@code com.landawn.abacus.util.stream.Stream} for more APIs docs. * * @param the type of the keys in the entries of the stream * @param the type of the values in the entries of the stream * * @see com.landawn.abacus.util.stream.BaseStream * @see com.landawn.abacus.util.stream.Stream * @see com.landawn.abacus.util.stream.Collectors * @see com.landawn.abacus.util.Fn * @see com.landawn.abacus.util.Comparators */ @com.landawn.abacus.annotation.Immutable @LazyEvaluation public final class EntryStream extends StreamBase, Object[], Predicate>, Consumer>, Optional>, Indexed>, ObjIterator>, EntryStream> { private static final Function, Stream>> mapper_func = Stream::of; final Map _map; //NOSONAR final Stream> _stream; //NOSONAR EntryStream(final Stream> s) { this(null, s); } @SuppressWarnings("rawtypes") EntryStream(final Map m, final Stream> s) { super(s.sorted, (Comparator>) s.cmp, s.closeHandlers); _map = (Map) m; _stream = (Stream>) s; } /** * Returns a stream of the keys from the entries in this EntryStream. * * @return A new Stream consisting of the keys from the entries in this EntryStream. * @see Stream#map(Function) * @see Fn#key() */ @SequentialOnly @IntermediateOp public Stream keys() { // It won't be parallel stream if m != null. if (_map != null) { return Stream.of(_map.keySet()); } final Function, K> func = Fn.key(); if (isParallel()) { return _stream.psp(ss -> ss.map(func)); } else { return _stream.map(func); } } /** * Returns a stream of the values from the entries in this EntryStream. * * @return A new Stream consisting of the values from the entries in this EntryStream. * @see Stream#map(Function) * @see Fn#value() */ @SequentialOnly @IntermediateOp public Stream values() { // It won't be parallel stream if m != null. if (_map != null) { return Stream.of(_map.values()); } final Function, V> func = Fn.value(); if (isParallel()) { return _stream.psp(ss -> ss.map(func)); } else { return _stream.map(func); } } /** * Returns a stream of the entries in this EntryStream. * * @return A new Stream consisting of the entries in this EntryStream. */ @SequentialOnly @IntermediateOp public Stream> entries() { return _stream; } /** * Inverts the key-value pairs in the EntryStream. * * @return a new EntryStream with inverted key-value pairs * @see #map(BiFunction) * @see Stream#map(Function) * @see Fn#inverse() */ @SequentialOnly @IntermediateOp public EntryStream inversed() { final Function, Map.Entry> mapper = Fn.inverse(); if (isParallel()) { return of(_stream.>> psp(ss -> ss.map(mapper))); } else { return map(mapper); } } /** * Returns a stream consisting of the elements of this stream which keys are instances of the given class. * * @param the type of keys to select * @param clazz the class to filter the keys * @return a new EntryStream with keys filtered by the specified class * @see #filterByKey(Predicate) */ @SequentialOnly @IntermediateOp public EntryStream selectByKey(final Class clazz) { if (isParallel()) { //noinspection resource return (EntryStream) sequential().filterByKey(Fn.instanceOf(clazz)) .parallel(maxThreadNum(), executorNumForVirtualThread(), splitor(), asyncExecutor(), cancelUncompletedThreads()); } else { return (EntryStream) filterByKey(Fn.instanceOf(clazz)); } } /** * Returns a stream consisting of the elements of this stream which values are instances of the given class. * * @param the type of values to select * @param clazz the class to filter the values * @return a new EntryStream with values filtered by the specified class * @see #filterByValue(Predicate) */ @SequentialOnly @IntermediateOp public EntryStream selectByValue(final Class clazz) { if (isParallel()) { //noinspection resource return (EntryStream) sequential().filterByValue(Fn.instanceOf(clazz)) .parallel(maxThreadNum(), executorNumForVirtualThread(), splitor(), asyncExecutor(), cancelUncompletedThreads()); } else { return (EntryStream) filterByValue(Fn.instanceOf(clazz)); } } /** * Filters the entries in this EntryStream based on the given predicate. * * @param predicate the predicate to apply to each entry to determine if it should be included * @return a new EntryStream with entries that match the given predicate * @see Stream#filter(Predicate) */ @Override public EntryStream filter(final Predicate> predicate) { return of(_stream.filter(predicate)); } /** * Filters the entries in this EntryStream based on the given predicate. * * @param predicate the predicate to apply to each entry to determine if it should be included * @return a new EntryStream with entries that match the given predicate * @see Stream#filter(Predicate) */ @ParallelSupported @IntermediateOp public EntryStream filter(final BiPredicate predicate) { return of(_stream.filter(Fn.Entries.p(predicate))); } /** * Filters the entries in this EntryStream based on the given predicate. * * @param predicate the predicate to apply to each entry to determine if it should be included * @param actionOnDroppedItem the action to apply to each entry that is dropped by the filter * @return a new EntryStream with entries that match the given predicate * @see Stream#filter(Predicate, Consumer) */ @Override public EntryStream filter(final Predicate> predicate, final Consumer> actionOnDroppedItem) { return of(_stream.filter(predicate, actionOnDroppedItem)); } /** * Filters the entries in this EntryStream based on the given key predicate. * * @param keyPredicate the predicate to apply to each key to determine if its entry should be included * @return a new EntryStream with entries that match the given key predicate * @see Stream#filter(Predicate) */ @ParallelSupported @IntermediateOp public EntryStream filterByKey(final Predicate keyPredicate) { final Predicate> predicate = Fn.testByKey(keyPredicate); return of(_stream.filter(predicate)); } /** * Filters the entries in this EntryStream based on the given value predicate. * * @param valuePredicate the predicate to apply to each value to determine if its entry should be included * @return a new EntryStream with entries that match the given value predicate */ @ParallelSupported @IntermediateOp public EntryStream filterByValue(final Predicate valuePredicate) { final Predicate> predicate = Fn.testByValue(valuePredicate); return of(_stream.filter(predicate)); } // /** // * // * @param // * @param predicate // * @return // * @deprecated // */ // @Deprecated // @Override // public EntryStream removeIf(final Predicate> predicate) { // return of(s.removeIf(predicate)); // } // // /** // * // * @param // * @param predicate // * @return // * @deprecated // */ // @ParallelSupported // @Deprecated // public EntryStream removeIf(final BiPredicate predicate) { // return of(s.removeIf(Fn.Entries.p(predicate))); // } // // @Deprecated // @Override // public EntryStream removeIf(Predicate> predicate, Consumer> actionOnDroppedItem) { // return of(s.removeIf(predicate, actionOnDroppedItem)); // } /** * Keeps the elements until the given predicate returns {@code false}. * The stream should be sorted, which means if x is the first element: {@code predicate.test(x)} returns {@code false}, any element y behind x: {@code predicate.test(y)} should return {@code false}. * * @param predicate the predicate to apply to each entry to determine if it should be included * @return a new EntryStream with entries that match the given predicate * @see Stream#takeWhile(Predicate) */ @Override public EntryStream takeWhile(final Predicate> predicate) { return of(_stream.takeWhile(predicate)); } /** * Keeps the elements until the given predicate returns {@code false}. * The stream should be sorted, which means if x is the first element: {@code predicate.test(x)} returns {@code false}, any element y behind x: {@code predicate.test(y)} should return {@code false}. * * @param predicate the predicate to apply to each entry to determine if it should be included * @return a new EntryStream with entries that match the given predicate * @see Stream#takeWhile(Predicate) */ @ParallelSupported @IntermediateOp public EntryStream takeWhile(final BiPredicate predicate) { return of(_stream.takeWhile(Fn.Entries.p(predicate))); } /** * Drops the elements from this EntryStream while the given predicate returns {@code true}. * * @param predicate the predicate to apply to each entry to determine if it should be dropped * @return a new EntryStream with entries that do not match the given predicate * @see Stream#dropWhile(Predicate) */ @Override public EntryStream dropWhile(final Predicate> predicate) { return of(_stream.dropWhile(predicate)); } /** * Drops the elements from this EntryStream while the given predicate returns {@code true}. * * @param predicate the predicate to apply to each entry to determine if it should be dropped * @return a new EntryStream with entries that do not match the given predicate * @see Stream#dropWhile(Predicate) */ @ParallelSupported @IntermediateOp public EntryStream dropWhile(final BiPredicate predicate) { return of(_stream.dropWhile(Fn.Entries.p(predicate))); } /** * Drops the elements from this EntryStream while the given predicate returns {@code true}, * and applies the specified action to each dropped element. * * @param predicate the predicate to apply to each entry to determine if it should be dropped * @param actionOnDroppedItem the action to apply to each entry that is dropped by the predicate * @return a new EntryStream with entries that do not match the given predicate * @see Stream#dropWhile(Predicate, Consumer) */ @Override public EntryStream dropWhile(final Predicate> predicate, final Consumer> actionOnDroppedItem) { return of(_stream.dropWhile(predicate, actionOnDroppedItem)); } /** * Skips elements from this EntryStream until the given predicate returns {@code true}. * * @param predicate the predicate to apply to each entry to determine if it should be skipped * @return a new EntryStream with entries starting from the first entry that matches the given predicate * @see Stream#skipUntil(Predicate) */ @Override public EntryStream skipUntil(final Predicate> predicate) { return of(_stream.skipUntil(predicate)); } /** * Skips elements from this EntryStream until the given predicate returns {@code true}. * * @param predicate the predicate to apply to each entry to determine if it should be skipped * @return a new EntryStream with entries starting from the first entry that matches the given predicate * @see Stream#skipUntil(Predicate) */ @ParallelSupported @IntermediateOp public EntryStream skipUntil(final BiPredicate predicate) { return of(_stream.skipUntil(Fn.Entries.p(predicate))); } /** * Transforms the entries in this EntryStream using the given mapper function. * * @param the type of the keys in the resulting entries * @param the type of the values in the resulting entries * @param mapper the function to apply to each entry to transform it * @return a new EntryStream with transformed entries * @see Stream#map(Function) */ @ParallelSupported @IntermediateOp public EntryStream map(final Function, ? extends Map.Entry> mapper) { return _stream.mapToEntry(mapper); } /** * Transforms the entries in this EntryStream using the given key and value extractor functions. * * @param the type of the keys in the resulting entries * @param the type of the values in the resulting entries * @param keyMapper the function to apply to each entry to extract the key * @param valueMapper the function to apply to each entry to extract the value * @return a new EntryStream with transformed entries */ @ParallelSupported @IntermediateOp public EntryStream map(final Function, ? extends KK> keyMapper, final Function, ? extends VV> valueMapper) { return _stream.mapToEntry(keyMapper, valueMapper); } /** * Transforms the entries in this EntryStream using the given BiFunction mapper. * * @param the type of the keys in the resulting entries * @param the type of the values in the resulting entries * @param mapper the BiFunction to apply to each entry to transform it * @return a new EntryStream with transformed entries * @see #map(BiFunction) * @see Stream#map(Function) */ @ParallelSupported @IntermediateOp public EntryStream map(final BiFunction> mapper) { return map(Fn.Entries.f(mapper)); } /** * Transforms the entries in this EntryStream using the given key and value extractor functions. * * @param the type of the keys in the resulting entries * @param the type of the values in the resulting entries * @param keyMapper the function to apply to each entry to extract the key * @param valueMapper the function to apply to each entry to extract the value * @return a new EntryStream with transformed entries */ @ParallelSupported @IntermediateOp public EntryStream map(final BiFunction keyMapper, final BiFunction valueMapper) { final Function, Map.Entry> mapper = t -> new SimpleImmutableEntry<>(keyMapper.apply(t.getKey(), t.getValue()), valueMapper.apply(t.getKey(), t.getValue())); return map(mapper); } /** * Applies a mapping operation on the stream with multiple output elements for each input element. * It takes a BiConsumer as an argument which is applied to each element in the stream and a Consumer that accepts multiple output elements. * The result is a new stream consisting of all output elements produced by the BiConsumer for each input element. * * @param the type of the keys in the resulting entries * @param the type of the values in the resulting entries * @param mapper the BiConsumer to apply to each entry to transform it * @return a new EntryStream with transformed entries * @see Stream#mapMulti(BiConsumer) */ @Beta @ParallelSupported @IntermediateOp public EntryStream mapMulti(final BiConsumer, ? super Consumer>> mapper) { return _stream.mapMulti(mapper).mapToEntry(Fn.identity()); } /** * Transforms the entries in this EntryStream using the given mapper function. * The mapper function returns an Optional containing the transformed entry or an empty Optional if the entry should be excluded. * * @param the type of the keys in the resulting entries * @param the type of the values in the resulting entries * @param mapper the function to apply to each entry to transform it * @return a new EntryStream with transformed entries * @see Stream#mapPartial(Function) */ @ParallelSupported @IntermediateOp public EntryStream mapPartial(final Function, Optional>> mapper) { return _stream.mapPartial(mapper).mapToEntry(Fn.identity()); } /** * Transforms the entries in this EntryStream using the given BiFunction mapper. * The mapper function returns an Optional containing the transformed entry or an empty Optional if the entry should be excluded. * * @param the type of the keys in the resulting entries * @param the type of the values in the resulting entries * @param mapper the BiFunction to apply to each entry to transform it * @return a new EntryStream with transformed entries * @see #mapPartial(Function) * @see Stream#mapPartial(Function) */ @ParallelSupported @IntermediateOp public EntryStream mapPartial(final BiFunction>> mapper) { return mapPartial(Fn.Entries.f(mapper)); } /** * Transforms the keys in this EntryStream using the given key mapper function. * * @param the type of the keys in the resulting entries * @param keyMapper the function to apply to each key to transform it * @return a new EntryStream with transformed keys * @see Stream#map(Function) */ @ParallelSupported @IntermediateOp public EntryStream mapKey(final Function keyMapper) { final Function, Map.Entry> mapper = Fn.mapKey(keyMapper); return map(mapper); } /** * Transforms the keys in this EntryStream using the given key mapper function. * * @param the type of the keys in the resulting entries * @param keyMapper the function to apply to each key to transform it * @return a new EntryStream with transformed keys * @see Stream#map(Function) */ @ParallelSupported @IntermediateOp public EntryStream mapKey(final BiFunction keyMapper) { final Function, Map.Entry> mapper = entry -> new SimpleImmutableEntry<>(keyMapper.apply(entry.getKey(), entry.getValue()), entry.getValue()); return map(mapper); } /** * Transforms the values in this EntryStream using the given value mapper function. * * @param the type of the values in the resulting entries * @param valueMapper the function to apply to each value to transform it * @return a new EntryStream with transformed values * @see Stream#map(Function) */ @ParallelSupported @IntermediateOp public EntryStream mapValue(final Function valueMapper) { final Function, Map.Entry> mapper = Fn.mapValue(valueMapper); return map(mapper); } /** * Transforms the values in this EntryStream using the given value mapper function. * * @param the type of the values in the resulting entries * @param valueMapper the function to apply to each value to transform it * @return a new EntryStream with transformed values * @see Stream#map(Function) */ @ParallelSupported @IntermediateOp public EntryStream mapValue(final BiFunction valueMapper) { final Function, Map.Entry> mapper = entry -> new SimpleImmutableEntry<>(entry.getKey(), valueMapper.apply(entry.getKey(), entry.getValue())); return map(mapper); } /** * Transforms the keys in this EntryStream using the given key mapper function. * The mapper function returns an Optional containing the transformed key or an empty Optional if the key should be excluded. * * @param the type of the keys in the resulting entries * @param keyMapper the function to apply to each key to transform it * @return a new EntryStream with transformed keys * @see Stream#mapPartial(Function) */ @ParallelSupported @IntermediateOp public EntryStream mapKeyPartial(final Function> keyMapper) { //NOSONAR final Map.Entry emptyEntry = new SimpleImmutableEntry<>(null, null); final Function, Map.Entry> mapper = entry -> { final Optional op = keyMapper.apply(entry.getKey()); return op.isPresent() ? new SimpleImmutableEntry<>(op.get(), entry.getValue()) : emptyEntry; }; if (this.isParallel()) { //noinspection resource return map(mapper).psp(s -> s.filter(it -> it != emptyEntry)); } else { //noinspection resource return map(mapper).filter(it -> it != emptyEntry); } } /** * Transforms the keys in this EntryStream using the given key mapper function. * The mapper function returns an Optional containing the transformed key or an empty Optional if the key should be excluded. * * @param the type of the keys in the resulting entries * @param keyMapper the function to apply to each key to transform it * @return a new EntryStream with transformed keys * @see Stream#mapPartial(Function) */ @ParallelSupported @IntermediateOp public EntryStream mapKeyPartial(final BiFunction> keyMapper) { //NOSONAR final Map.Entry emptyEntry = new SimpleImmutableEntry<>(null, null); final Function, Map.Entry> mapper = entry -> { final Optional op = keyMapper.apply(entry.getKey(), entry.getValue()); return op.isPresent() ? new SimpleImmutableEntry<>(op.get(), entry.getValue()) : emptyEntry; }; if (this.isParallel()) { //noinspection resource return map(mapper).psp(s -> s.filter(it -> it != emptyEntry)); } else { //noinspection resource return map(mapper).filter(it -> it != emptyEntry); } } /** * Transforms the values in this EntryStream using the given value mapper function. * The mapper function returns an Optional containing the transformed value or an empty Optional if the value should be excluded. * * @param the type of the values in the resulting entries * @param valueMapper the function to apply to each value to transform it * @return a new EntryStream with transformed values * @see Stream#mapPartial(Function) */ @ParallelSupported @IntermediateOp public EntryStream mapValuePartial(final Function> valueMapper) { //NOSONAR final Map.Entry emptyEntry = new SimpleImmutableEntry<>(null, null); final Function, Map.Entry> mapper = entry -> { final Optional op = valueMapper.apply(entry.getValue()); return op.isPresent() ? new SimpleImmutableEntry<>(entry.getKey(), op.get()) : emptyEntry; }; if (this.isParallel()) { //noinspection resource return map(mapper).psp(s -> s.filter(it -> it != emptyEntry)); } else { //noinspection resource return map(mapper).filter(it -> it != emptyEntry); } } /** * Transforms the values in this EntryStream using the given value mapper function. * The mapper function returns an Optional containing the transformed value or an empty Optional if the value should be excluded. * * @param the type of the values in the resulting entries * @param valueMapper the function to apply to each value to transform it * @return a new EntryStream with transformed values * @see Stream#mapPartial(Function) */ @ParallelSupported @IntermediateOp public EntryStream mapValuePartial(final BiFunction> valueMapper) { //NOSONAR final Map.Entry emptyEntry = new SimpleImmutableEntry<>(null, null); final Function, Map.Entry> mapper = entry -> { final Optional op = valueMapper.apply(entry.getKey(), entry.getValue()); return op.isPresent() ? new SimpleImmutableEntry<>(entry.getKey(), op.get()) : emptyEntry; }; if (this.isParallel()) { //noinspection resource return map(mapper).psp(s -> s.filter(it -> it != emptyEntry)); } else { //noinspection resource return map(mapper).filter(it -> it != emptyEntry); } } /** * Applies a mapping operation on the stream with multiple output elements for each input element. * It takes a Function as an argument which is applied to each element in the stream. * The result is a new EntryStream consisting of all output elements produced by the Function for each input element. * * @param the type of the keys in the resulting entries * @param the type of the values in the resulting entries * @param mapper the Function to apply to each entry to transform it * @return a new EntryStream with transformed entries * @see Stream#flatMap(Function) * @see Stream#flatmap(Function) */ @ParallelSupported @IntermediateOp public EntryStream flatMap(final Function, ? extends EntryStream> mapper) { //NOSONAR return _stream.flattMapToEntry(mapper); } /** * Applies a mapping operation on the stream with multiple output elements for each input element. * It takes a BiFunction as an argument which is applied to each element in the stream. * The result is a new EntryStream consisting of all output elements produced by the BiFunction for each input element. * * @param the type of the keys in the resulting entries * @param the type of the values in the resulting entries * @param mapper the BiFunction to apply to each entry to transform it * @return a new EntryStream with transformed entries * @see #flatMap(Function) * @see Stream#flatMap(Function) * @see Stream#flatmap(Function) */ @ParallelSupported @IntermediateOp public EntryStream flatMap(final BiFunction> mapper) { //NOSONAR return flatMap(Fn.Entries.f(mapper)); } /** * Applies a mapping operation on the stream with multiple output elements for each input element. * It takes a Function as an argument which is applied to each element in the stream. * The result is a new Map consisting of all output elements produced by the Function for each input element. * * @param the type of the keys in the resulting entries * @param the type of the values in the resulting entries * @param mapper the Function to apply to each entry to transform it * @return a new EntryStream with transformed entries * @see Stream#flatMap(Function) * @see Stream#flatmap(Function) */ @ParallelSupported @IntermediateOp public EntryStream flatmap(final Function, ? extends Map> mapper) { //NOSONAR return _stream.flatmapToEntry(mapper); } /** * Applies a mapping operation on the stream with multiple output elements for each input element. * It takes a BiFunction as an argument which is applied to each element in the stream. * The result is a new Map consisting of all output elements produced by the BiFunction for each input element. * * @param the type of the keys in the resulting entries * @param the type of the values in the resulting entries * @param mapper the BiFunction to apply to each entry to transform it * @return a new EntryStream with transformed entries * @see #flatmap(Function) * @see Stream#flatMap(Function) * @see Stream#flatmap(Function) */ @ParallelSupported @IntermediateOp public EntryStream flatmap(final BiFunction> mapper) { //NOSONAR return flatmap(Fn.Entries.f(mapper)); } /** * Applies a mapping operation on the stream with multiple output elements for each input element. * It takes a Function as an argument which is applied to each element in the stream. * The result is a new Stream consisting of all output elements produced by the Function for each input element. * * @param the type of the keys in the resulting entries * @param the type of the values in the resulting entries * @param mapper the Function to apply to each entry to transform it * @return a new EntryStream with transformed entries * @see Stream#flatMap(Function) * @see Stream#flatmap(Function) */ @ParallelSupported @IntermediateOp @Beta public EntryStream flattMap( final Function, ? extends Stream>> mapper) { return _stream.flatMapToEntry(mapper); } /** * Applies a mapping operation on the stream with multiple output elements for each input element. * It takes a BiFunction as an argument which is applied to each element in the stream. * The result is a new Stream consisting of all output elements produced by the BiFunction for each input element. * * @param the type of the keys in the resulting entries * @param the type of the values in the resulting entries * @param mapper the BiFunction to apply to each entry to transform it * @return a new EntryStream with transformed entries * @see #flattMap(Function) * @see Stream#flatMap(Function) * @see Stream#flatmap(Function) */ @ParallelSupported @IntermediateOp @Beta public EntryStream flattMap( final BiFunction>> mapper) { return flattMap(Fn.Entries.f(mapper)); } /** * Applies a mapping operation on the keys in this EntryStream with multiple output elements for each input key. * It takes a Function as an argument which is applied to each key in the stream. * The result is a new Stream consisting of all output keys produced by the Function for each input key. * * @param the type of the keys in the resulting entries * @param keyMapper the Function to apply to each key to transform it * @return a new EntryStream with transformed keys * @see Stream#flatMap(Function) * @see Stream#flatmap(Function) */ @ParallelSupported @IntermediateOp public EntryStream flatMapKey(final Function> keyMapper) { final Function, Stream>> mapper2 = e -> keyMapper.apply(e.getKey()) .map(kk -> new SimpleImmutableEntry<>(kk, e.getValue())); return flattMap(mapper2); } /** * Applies a mapping operation on the keys in this EntryStream with multiple output elements for each input key. * It takes a BiFunction as an argument which is applied to each key in the stream. * The result is a new Stream consisting of all output keys produced by the BiFunction for each input key. * * @param the type of the keys in the resulting entries * @param keyMapper the BiFunction to apply to each key to transform it * @return a new EntryStream with transformed keys * @see #flatMapKey(Function) * @see Stream#flatMap(Function) * @see Stream#flatmap(Function) */ @ParallelSupported @IntermediateOp public EntryStream flatMapKey(final BiFunction> keyMapper) { final Function, Stream>> mapper2 = e -> keyMapper.apply(e.getKey(), e.getValue()) .map(kk -> new SimpleImmutableEntry<>(kk, e.getValue())); return flattMap(mapper2); } /** * Applies a mapping operation on the keys in this EntryStream with multiple output elements for each input key. * It takes a Function as an argument which is applied to each key in the stream. * The result is a new Collection consisting of all output keys produced by the Function for each input key. * * @param the type of the keys in the resulting entries * @param keyMapper the Function to apply to each key to transform it * @return a new EntryStream with transformed keys * @see Stream#flatMap(Function) * @see Stream#flatmap(Function) */ @ParallelSupported @IntermediateOp public EntryStream flatmapKey(final Function> keyMapper) { //NOSONAR @SuppressWarnings("resource") final Function, Stream>> mapper2 = e -> Stream.of(keyMapper.apply(e.getKey())) .map(kk -> new SimpleImmutableEntry<>(kk, e.getValue())); return flattMap(mapper2); } /** * Applies a mapping operation on the keys in this EntryStream with multiple output elements for each input key. * It takes a BiFunction as an argument which is applied to each key in the stream. * The result is a new Collection consisting of all output keys produced by the BiFunction for each input key. * * @param the type of the keys in the resulting entries * @param keyMapper the BiFunction to apply to each key to transform it * @return a new EntryStream with transformed keys * @see #flatMapKey(Function) * @see Stream#flatMap(Function) * @see Stream#flatmap(Function) */ @ParallelSupported @IntermediateOp public EntryStream flatmapKey(final BiFunction> keyMapper) { //NOSONAR @SuppressWarnings("resource") final Function, Stream>> mapper2 = e -> Stream.of(keyMapper.apply(e.getKey(), e.getValue())) .map(kk -> new SimpleImmutableEntry<>(kk, e.getValue())); return flattMap(mapper2); } /** * Applies a mapping operation on the values in this EntryStream with multiple output elements for each input value. * It takes a Function as an argument which is applied to each value in the stream. * The result is a new Stream consisting of all output values produced by the Function for each input value. * * @param the type of the values in the resulting entries * @param valueMapper the Function to apply to each value to transform it * @return a new EntryStream with transformed values * @see Stream#flatMap(Function) * @see Stream#flatmap(Function) */ @ParallelSupported @IntermediateOp public EntryStream flatMapValue(final Function> valueMapper) { final Function, Stream>> mapper2 = e -> valueMapper.apply(e.getValue()) .map(vv -> new SimpleImmutableEntry<>(e.getKey(), vv)); return flattMap(mapper2); } /** * Applies a mapping operation on the values in this EntryStream with multiple output elements for each input value. * It takes a BiFunction as an argument which is applied to each value in the stream. * The result is a new Stream consisting of all output values produced by the BiFunction for each input value. * * @param the type of the values in the resulting entries * @param valueMapper the BiFunction to apply to each value to transform it * @return a new EntryStream with transformed values * @see #flatMapValue(Function) * @see Stream#flatMap(Function) * @see Stream#flatmap(Function) */ @ParallelSupported @IntermediateOp public EntryStream flatMapValue(final BiFunction> valueMapper) { final Function, Stream>> mapper2 = e -> valueMapper.apply(e.getKey(), e.getValue()) .map(vv -> new SimpleImmutableEntry<>(e.getKey(), vv)); return flattMap(mapper2); } /** * Applies a mapping operation on the values in this EntryStream with multiple output elements for each input value. * It takes a Function as an argument which is applied to each value in the stream. * The result is a new Collection consisting of all output values produced by the Function for each input value. * * @param the type of the values in the resulting entries * @param valueMapper the Function to apply to each value to transform it * @return a new EntryStream with transformed values * @see Stream#flatMap(Function) * @see Stream#flatmap(Function) */ @ParallelSupported @IntermediateOp public EntryStream flatmapValue(final Function> valueMapper) { //NOSONAR @SuppressWarnings("resource") final Function, Stream>> mapper2 = e -> Stream.of(valueMapper.apply(e.getValue())) .map(vv -> new SimpleImmutableEntry<>(e.getKey(), vv)); return flattMap(mapper2); } /** * Applies a mapping operation on the values in this EntryStream with multiple output elements for each input value. * It takes a BiFunction as an argument which is applied to each value in the stream. * The result is a new Collection consisting of all output values produced by the BiFunction for each input value. * * @param the type of the values in the resulting entries * @param valueMapper the BiFunction to apply to each value to transform it * @return a new EntryStream with transformed values * @see #flatMapValue(Function) * @see Stream#flatMap(Function) * @see Stream#flatmap(Function) */ @ParallelSupported @IntermediateOp public EntryStream flatmapValue(final BiFunction> valueMapper) { //NOSONAR @SuppressWarnings("resource") final Function, Stream>> mapper2 = e -> Stream.of(valueMapper.apply(e.getKey(), e.getValue())) .map(vv -> new SimpleImmutableEntry<>(e.getKey(), vv)); return flattMap(mapper2); } /** * Groups the entries in this EntryStream by their keys. * The result is a new EntryStream where each key is associated with a list of values. * * @return a new EntryStream with keys and their associated list of values * @see Stream#groupBy(Function, Function) * @see Fn#key() * @see Fn#value() */ @SequentialOnly @IntermediateOp @TerminalOpTriggered public EntryStream> groupBy() { final Function, K> keyMapper = Fn.key(); final Function, V> valueMapper = Fn.value(); if (isParallel()) { return of(_stream.sequential() .groupBy(keyMapper, valueMapper) .parallel(_stream.maxThreadNum(), _stream.executorNumForVirtualThread(), _stream.splitor(), _stream.asyncExecutor(), _stream.cancelUncompletedThreads())); } else { return of(_stream.groupBy(keyMapper, valueMapper)); } } /** * Groups the entries in this EntryStream by their keys. * The result is a new EntryStream where each key is associated with a list of values. * * @param mapFactory The supplier providing a new empty Map into which the results will be inserted. * @return a new EntryStream with keys and their associated list of values * @see Stream#groupBy(Function, Function, Supplier) */ @SequentialOnly @IntermediateOp @TerminalOpTriggered public EntryStream> groupBy(final Supplier>> mapFactory) { final Function, K> keyMapper = Fn.key(); final Function, V> valueMapper = Fn.value(); if (isParallel()) { return of(_stream.sequential() .groupBy(keyMapper, valueMapper, mapFactory) .parallel(_stream.maxThreadNum(), _stream.executorNumForVirtualThread(), _stream.splitor(), _stream.asyncExecutor(), _stream.cancelUncompletedThreads())); } else { return of(_stream.groupBy(keyMapper, valueMapper, mapFactory)); } } /** * Groups the elements of the stream by applying a key mapping function and a value mapping function to each element. * The result is an EntryStream where each entry's key is the group identifier (determined by the key mapping function), * and the value is a list of elements that are mapped to the corresponding key by the value mapping function. * This is an intermediate operation. * * @param The type of the key in the resulting Map.Entry. * @param The type of the value in the resulting Map.Entry. * @param keyMapper The function to be applied to each element in the stream to determine the group it belongs to. * @param valueMapper The function to be applied to each element in the stream to determine its value in the group. * @return A new EntryStream consisting of entries where the key is the group identifier, and the value is a list of elements that mapped to the corresponding key. * @see Stream#groupBy(Function, Function) */ @ParallelSupported @IntermediateOp @TerminalOpTriggered public EntryStream> groupBy(final Function, ? extends KK> keyMapper, final Function, ? extends VV> valueMapper) { return of(_stream.groupBy(keyMapper, valueMapper)); } /** * Groups the elements of the stream by applying a key mapping function and a value mapping function to each element. * The result is an EntryStream where each entry's key is the group identifier (determined by the key mapping function), * and the value is a list of elements that are mapped to the corresponding key by the value mapping function. * This is an intermediate operation. * * @param The type of the key in the resulting Map.Entry. * @param The type of the value in the resulting Map.Entry. * @param keyMapper The function to be applied to each element in the stream to determine the group it belongs to. * @param valueMapper The function to be applied to each element in the stream to determine its value in the group. * @param mapFactory The supplier providing a new empty Map into which the results will be inserted. * @return A new EntryStream consisting of entries where the key is the group identifier, and the value is a list of elements that mapped to the corresponding key. * @see Stream#groupBy(Function, Function, Supplier) */ @ParallelSupported @IntermediateOp @TerminalOpTriggered public EntryStream> groupBy(final Function, ? extends KK> keyMapper, final Function, ? extends VV> valueMapper, final Supplier>> mapFactory) { return of(_stream.groupBy(keyMapper, valueMapper, mapFactory)); } /** * Groups the entries in this EntryStream by their keys. * The result is a new EntryStream where each key is associated with the result of the downstream collector. * * @param the type of the result of the downstream collector * @param downstream the collector to use for grouping the entries * @return a new EntryStream with keys and their associated collected results * @see Stream#groupBy(Function, Collector) */ @ParallelSupported @IntermediateOp @TerminalOpTriggered public EntryStream groupBy(final Collector, ?, D> downstream) { final Function, K> keyMapper = Fn.key(); return of(_stream.groupBy(keyMapper, downstream)); } /** * Groups the entries in this EntryStream by their keys. * The result is a new EntryStream where each key is associated with the result of the downstream collector. * * @param the type of the result of the downstream collector * @param downstream the collector to use for grouping the entries * @param mapFactory The supplier providing a new empty Map into which the results will be inserted. * @return a new EntryStream with keys and their associated collected results * @see Stream#groupBy(Function, Collector, Supplier) */ @ParallelSupported @IntermediateOp @TerminalOpTriggered public EntryStream groupBy(final Collector, ?, D> downstream, final Supplier> mapFactory) { final Function, K> keyMapper = Fn.key(); return of(_stream.groupBy(keyMapper, downstream, mapFactory)); } /** * Groups the elements of the stream by applying a key mapping function to each element. * The result is an EntryStream where each entry's key is the group identifier (determined by the key mapping function), * and the value is the result of the downstream collector. * * @param The type of the key in the resulting Map.Entry. * @param The type of the result of the downstream collector. * @param keyMapper The function to be applied to each element in the stream to determine the group it belongs to. * @param downstream The collector to use for grouping the entries. * @return A new EntryStream consisting of entries where the key is the group identifier and the value is the result of the downstream collector. * @see Stream#groupBy(Function, Collector) */ @ParallelSupported @IntermediateOp @TerminalOpTriggered public EntryStream groupBy(final Function, ? extends KK> keyMapper, final Collector, ?, D> downstream) { return of(_stream.groupBy(keyMapper, downstream)); } /** * Groups the elements of the stream by applying a key mapping function to each element. * The result is an EntryStream where each entry's key is the group identifier (determined by the key mapping function), * and the value is the result of the downstream collector. * * @param The type of the key in the resulting Map.Entry. * @param The type of the result of the downstream collector. * @param keyMapper The function to be applied to each element in the stream to determine the group it belongs to. * @param downstream The collector to use for grouping the entries. * @param mapFactory The supplier providing a new empty Map into which the results will be inserted. * @return A new EntryStream consisting of entries where the key is the group identifier and the value is the result of the downstream collector. * @see Stream#groupBy(Function, Collector, Supplier) */ @ParallelSupported @IntermediateOp @TerminalOpTriggered public EntryStream groupBy(final Function, ? extends KK> keyMapper, final Collector, ?, D> downstream, final Supplier> mapFactory) { return of(_stream.groupBy(keyMapper, downstream, mapFactory)); } /** * Groups the entries in this EntryStream by their keys. * The result is a new EntryStream where each key is associated with a single value, * which is the result of applying the merge function to all values associated with that key. * * @param mergeFunction the function to merge values associated with the same key * @return a new EntryStream with keys and their associated merged values * @see Stream#groupBy(Function, Function, BinaryOperator) */ @SequentialOnly @IntermediateOp @TerminalOpTriggered public EntryStream groupBy(final BinaryOperator mergeFunction) { final Function, K> keyMapper = Fn.key(); final Function, V> valueMapper = Fn.value(); if (isParallel()) { return of(_stream.sequential() .groupBy(keyMapper, valueMapper, mergeFunction) .parallel(_stream.maxThreadNum(), _stream.executorNumForVirtualThread(), _stream.splitor(), _stream.asyncExecutor(), _stream.cancelUncompletedThreads())); } else { return of(_stream.groupBy(keyMapper, valueMapper, mergeFunction)); } } /** * Groups the entries in this EntryStream by their keys. * The result is a new EntryStream where each key is associated with a single value, * which is the result of applying the merge function to all values associated with that key. * * @param mergeFunction the function to merge values associated with the same key * @param mapFactory The supplier providing a new empty Map into which the results will be inserted. * @return a new EntryStream with keys and their associated merged values * @see Stream#groupBy(Function, Function, BinaryOperator, Supplier) */ @SequentialOnly @IntermediateOp @TerminalOpTriggered public EntryStream groupBy(final BinaryOperator mergeFunction, final Supplier> mapFactory) { final Function, K> keyMapper = Fn.key(); final Function, V> valueMapper = Fn.value(); if (isParallel()) { return of(_stream.sequential() .groupBy(keyMapper, valueMapper, mergeFunction, mapFactory) .parallel(_stream.maxThreadNum(), _stream.executorNumForVirtualThread(), _stream.splitor(), _stream.asyncExecutor(), _stream.cancelUncompletedThreads())); } else { return of(_stream.groupBy(keyMapper, valueMapper, mergeFunction, mapFactory)); } } /** * Groups the elements of the stream by applying a key mapping function and a value mapping function to each element, * and then merges the values associated with the same key using the provided merge function. * The result is an EntryStream where each entry's key is the group identifier (determined by the key mapping function), * and the value is the result of merging the values that mapped to the corresponding key. * * @param The type of the key in the resulting Map.Entry. * @param The type of the value in the resulting Map.Entry. * @param keyMapper The function to be applied to each element in the stream to determine the group it belongs to. * @param valueMapper The function to be applied to each element in the stream to determine its value in the group. * @param mergeFunction The function to merge values associated with the same key. * @return A new EntryStream consisting of entries where the key is the group identifier and the value is the result of merging the values that mapped to the corresponding key. * @see Stream#groupBy(Function, Function, BinaryOperator) */ @ParallelSupported @IntermediateOp @TerminalOpTriggered public EntryStream groupBy(final Function, ? extends KK> keyMapper, final Function, ? extends VV> valueMapper, final BinaryOperator mergeFunction) { return of(_stream.groupBy(keyMapper, valueMapper, mergeFunction)); } /** * Groups the elements of the stream by applying a key mapping function and a value mapping function to each element, * and then merges the values associated with the same key using the provided merge function. * The result is an EntryStream where each entry's key is the group identifier (determined by the key mapping function), * and the value is the result of merging the values that mapped to the corresponding key. * * @param The type of the key in the resulting Map.Entry. * @param The type of the value in the resulting Map.Entry. * @param keyMapper The function to be applied to each element in the stream to determine the group it belongs to. * @param valueMapper The function to be applied to each element in the stream to determine its value in the group. * @param mergeFunction The function to merge values associated with the same key. * @param mapFactory The supplier providing a new empty Map into which the results will be inserted. * @return A new EntryStream consisting of entries where the key is the group identifier and the value is the result of merging the values that mapped to the corresponding key. * @see Stream#groupBy(Function, Function, BinaryOperator, Supplier) */ @ParallelSupported @IntermediateOp @TerminalOpTriggered public EntryStream groupBy(final Function, ? extends KK> keyMapper, final Function, ? extends VV> valueMapper, final BinaryOperator mergeFunction, final Supplier> mapFactory) { return of(_stream.groupBy(keyMapper, valueMapper, mergeFunction, mapFactory)); } /** * Collapse the entries in this EntryStream based on the given key predicate. * The entries are grouped into lists of values where the corresponding keys are collapsible. * * @param collapsible the predicate to determine if two keys are collapsible * @return a new Stream with lists of values whose keys are collapsible * @see #collapseByKey(BiPredicate, Function, Collector) * @see Stream#collapse(BiPredicate, Collector) */ @SequentialOnly @IntermediateOp public Stream> collapseByKey(final BiPredicate collapsible) { return collapseByKey(collapsible, Fn.value(), Collectors.toList()); } /** * Collapse the entries in this EntryStream based on the given key predicate. * The entries are mapped using the provided mapper function and collected using the specified collector. * * @param the type of the mapped elements * @param the type of the result * @param collapsible the predicate to determine if two keys are collapsible * @param mapper the function to map each entry to a value * @param collector the collector to collect the mapped values * @return a new Stream with the collapsed and collected results * @see Stream#collapse(BiPredicate, Collector) */ @SequentialOnly @IntermediateOp public Stream collapseByKey(final BiPredicate collapsible, final Function, U> mapper, final Collector collector) { final BiPredicate, ? super Map.Entry> collapsible2 = (t, u) -> collapsible.test(t.getKey(), u.getKey()); return _stream.collapse(collapsible2, Collectors.mapping(mapper, collector)); } /** * Collapse the entries in this EntryStream based on the given value predicate. * The entries are grouped into lists of keys where the corresponding values are collapsible. * * @param collapsible the predicate to determine if two values are collapsible * @return a new Stream with lists of keys whose values are collapsible * @see #collapseByValue(BiPredicate, Function, Collector) * @see Stream#collapse(BiPredicate, Collector) */ @SequentialOnly @IntermediateOp public Stream> collapseByValue(final BiPredicate collapsible) { return collapseByValue(collapsible, Fn.key(), Collectors.toList()); } /** * Collapse the entries in this EntryStream based on the given value predicate. * The entries are mapped using the provided mapper function and collected using the specified collector. * * @param the type of the mapped elements * @param the type of the result * @param collapsible the predicate to determine if two values are collapsible * @param mapper the function to map each entry to a value * @param collector the collector to collect the mapped values * @return a new Stream with the collapsed and collected results * @see Stream#collapse(BiPredicate, Collector) */ @SequentialOnly @IntermediateOp public Stream collapseByValue(final BiPredicate collapsible, final Function, U> mapper, final Collector collector) { final BiPredicate, ? super Map.Entry> collapsible2 = (t, u) -> collapsible.test(t.getValue(), u.getValue()); return _stream.collapse(collapsible2, Collectors.mapping(mapper, collector)); } /** * Splits the stream into chunks of the specified size. * Each chunk is collected into a List of Map.Entry objects. * This is an intermediate operation and can only be processed sequentially. * * @param chunkSize The size of each chunk. * @return A new Stream consisting of Lists of Map.Entry objects, each representing a chunk of the original Stream. * @see Stream#split(int) */ @SequentialOnly @IntermediateOp public Stream>> split(final int chunkSize) { return _stream.split(chunkSize); } /** * Splits the stream into chunks of the specified size. * Each chunk is collected into a collection of Map.Entry objects specified by the collectionSupplier. * This is an intermediate operation and can only be processed sequentially. * * @param The type of the collection to store the chunks. * @param chunkSize The size of each chunk. * @param collectionSupplier A function which returns a new, empty collection of the appropriate type. * @return A new Stream consisting of collections of Map.Entry objects, each representing a chunk of the original Stream. * @see Stream#split(int, IntFunction) */ @SequentialOnly @IntermediateOp public >> Stream split(final int chunkSize, final IntFunction collectionSupplier) { return _stream.split(chunkSize, collectionSupplier); } /** * Creates a sliding window over the elements of the Stream, where each window is a List of Map.Entry objects. * The window moves over the elements of the Stream according to the specified window size. * This is an intermediate operation and can only be processed sequentially. * *

Example: *

     * 
     * EntryStream.of(map).sliding(3) => [[entry1, entry2, entry3], [entry2, entry3, entry4], ...]
     * 
     * 
* * @param windowSize The size of the window to be used for sliding over the Stream elements. * @return A new Stream where each element is a List of Map.Entry objects from the original Stream, representing a window. */ @SequentialOnly @IntermediateOp public Stream>> sliding(final int windowSize) { return _stream.sliding(windowSize); } /** * Creates a sliding window over the elements of the Stream, where each window is a collection of Map.Entry objects specified by the collectionSupplier. * The window moves over the elements of the Stream according to the specified window size. * This is an intermediate operation and can only be processed sequentially. * *

Example: *

     * 
     * EntryStream.of(map).sliding(3, LinkedList::new) => [[entry1, entry2, entry3], [entry2, entry3, entry4], ...]
     * 
     * 
* * @param The type of the collection to store the windows. * @param windowSize The size of the window to be used for sliding over the Stream elements. * @param collectionSupplier A function which returns a new, empty collection of the appropriate type. * @return A new Stream where each element is a collection of Map.Entry objects from the original Stream, representing a window. */ @SequentialOnly @IntermediateOp public >> Stream sliding(final int windowSize, final IntFunction collectionSupplier) { return _stream.sliding(windowSize, collectionSupplier); } /** * Creates a sliding window over the elements of the Stream, where each window is a List of Map.Entry objects. * The window moves over the elements of the Stream according to the specified window size and increment. * This is an intermediate operation and can only be processed sequentially. * *

Example: *

     * 
     * EntryStream.of(map).sliding(3, 2) => [[entry1, entry2, entry3], [entry3, entry4, entry5], ...]
     * 
     * 
* * @param windowSize The size of the window to be used for sliding over the Stream elements. * @param increment The number of elements to move the window forward after each step. * @return A new Stream where each element is a List of Map.Entry objects from the original Stream, representing a window. */ @SequentialOnly @IntermediateOp public Stream>> sliding(final int windowSize, final int increment) { return _stream.sliding(windowSize, increment); } /** * Creates a sliding window over the elements of the Stream, where each window is a collection of Map.Entry objects specified by the collectionSupplier. * The window moves over the elements of the Stream according to the specified window size and increment. * This is an intermediate operation and can only be processed sequentially. * *

Example: *

     * 
     * EntryStream.of(map).sliding(3, 2, LinkedList::new) => [[entry1, entry2, entry3], [entry3, entry4, entry5], ...]
     * 
     * 
* * @param The type of the collection to store the windows. * @param windowSize The size of the window to be used for sliding over the Stream elements. * @param increment The number of elements to move the window forward after each step. * @param collectionSupplier A function which returns a new, empty collection of the appropriate type. * @return A new Stream where each element is a collection of Map.Entry objects from the original Stream, representing a window. */ @SequentialOnly @IntermediateOp public >> Stream sliding(final int windowSize, final int increment, final IntFunction collectionSupplier) { return _stream.sliding(windowSize, increment, collectionSupplier); } /** * Returns an EntryStream consisting of the elements of this stream that are also present in the specified collection. Occurrences are considered. * The order of the elements in the stream is preserved. * *
* This method only runs sequentially, even in parallel stream. * * @param c The collection to be used for intersection. * @return A new EntryStream consisting of the elements that are present in both this stream and the specified collection. * @see N#intersection(int[], int[]) * @see N#intersection(Collection, Collection) * @see N#commonSet(Collection, Collection) * @see Collection#retainAll(Collection) */ @Override public EntryStream intersection(final Collection c) { return of(_stream.intersection(c)); } /** * Returns an EntryStream consisting of the elements of this stream that are not present in the specified collection. Occurrences are considered. * The order of the elements in the stream is preserved. * *
* This method only runs sequentially, even in parallel stream. * * @param c The collection to be used for difference. * @return A new EntryStream consisting of the elements that are present in this stream but not in the specified collection. * @see IntList#difference(IntList) * @see N#difference(Collection, Collection) * @see N#symmetricDifference(Collection, Collection) * @see N#excludeAll(Collection, Collection) * @see N#excludeAllToSet(Collection, Collection) * @see N#removeAll(Collection, Iterable) * @see N#intersection(Collection, Collection) * @see N#commonSet(Collection, Collection) * @see Difference#of(Collection, Collection) */ @Override public EntryStream difference(final Collection c) { return of(_stream.difference(c)); } /** * Returns an EntryStream consisting of the elements of this stream that are not present in the specified collection and vice versa. Occurrences are considered. * The order of the elements in the stream is preserved. * *
* This method only runs sequentially, even in parallel stream. * * @param c The collection to be used for symmetric difference. * @return A new EntryStream consisting of the elements that are present in this stream but not in the specified collection and the elements that are present in the specified collection but not in this stream. * @see N#symmetricDifference(int[], int[]) * @see N#excludeAll(Collection, Collection) * @see N#excludeAllToSet(Collection, Collection) * @see N#difference(Collection, Collection) * @see Difference#of(Collection, Collection) * @see Iterables#symmetricDifference(Set, Set) */ @Override public EntryStream symmetricDifference(final Collection> c) { return of(_stream.symmetricDifference(c)); } /** * Returns a sorted EntryStream based on the natural ordering of the keys and values. * The entries are sorted first by key and then by value. * * @return a new EntryStream with entries sorted by key and value * @deprecated Use {@link #sorted(Comparator)} instead. */ @Deprecated @Override @SuppressWarnings("rawtypes") public EntryStream sorted() { final Comparator> cmp = Comparators. comparingByKey((Comparator) Comparators.naturalOrder()) .thenComparing(Comparators.comparingByValue((Comparator) Comparators.naturalOrder())); return of(_stream.sorted(cmp)); } /** * Returns a sorted EntryStream based on the specified comparator. * The entries are sorted according to the order induced by the specified comparator. * * @param comparator the comparator to compare the entries * @return a new EntryStream with entries sorted by the specified comparator */ @ParallelSupported @IntermediateOp @TerminalOpTriggered public EntryStream sorted(final Comparator> comparator) { return of(_stream.sorted(comparator)); } /** * Returns a sorted EntryStream based on the specified key comparator. * The entries are sorted according to the order induced by the specified key comparator. * * @param keyComparator the comparator to compare the keys * @return a new EntryStream with entries sorted by the specified key comparator */ @ParallelSupported @IntermediateOp @TerminalOpTriggered public EntryStream sortedByKey(final Comparator keyComparator) { final Comparator> comparator = Comparators.comparingByKey(keyComparator); return of(_stream.sorted(comparator)); } /** * Returns a sorted EntryStream based on the specified value comparator. * The entries are sorted according to the order induced by the specified value comparator. * * @param valueComparator the comparator to compare the values * @return a new EntryStream with entries sorted by the specified value comparator */ @ParallelSupported @IntermediateOp @TerminalOpTriggered public EntryStream sortedByValue(final Comparator valueComparator) { final Comparator> comparator = Comparators.comparingByValue(valueComparator); return of(_stream.sorted(comparator)); } /** * Returns a sorted EntryStream based on the specified key extractor function. * The entries are sorted according to the natural ordering of the extracted keys. Nulls are considered smaller than non-nulls. * * @param keyMapper the function to extract the key for comparison * @return a new EntryStream with entries sorted by the extracted keys */ @ParallelSupported @IntermediateOp @TerminalOpTriggered @SuppressWarnings("rawtypes") public EntryStream sortedBy(final Function, ? extends Comparable> keyMapper) { return of(_stream.sortedBy(keyMapper)); } /** * Returns a sorted EntryStream based on the specified key extractor function. * The entries are sorted according to the integer values extracted from the keys. * * @param keyMapper the function to extract the integer key for comparison * @return a new EntryStream with entries sorted by the extracted integer keys */ @ParallelSupported @IntermediateOp @TerminalOpTriggered public EntryStream sortedByInt(final ToIntFunction> keyMapper) { final Comparator> comparator = Comparators.comparingInt(keyMapper); return sorted(comparator); } /** * Returns a sorted EntryStream based on the specified key extractor function. * The entries are sorted according to the long values extracted from the keys. * * @param keyMapper the function to extract the long key for comparison * @return a new EntryStream with entries sorted by the extracted long keys */ @ParallelSupported @IntermediateOp @TerminalOpTriggered public EntryStream sortedByLong(final ToLongFunction> keyMapper) { final Comparator> comparator = Comparators.comparingLong(keyMapper); return sorted(comparator); } /** * Returns a sorted EntryStream based on the specified key extractor function. * The entries are sorted according to the double values extracted from the keys. * * @param keyMapper the function to extract the double key for comparison * @return a new EntryStream with entries sorted by the extracted double keys */ @ParallelSupported @IntermediateOp @TerminalOpTriggered public EntryStream sortedByDouble(final ToDoubleFunction> keyMapper) { final Comparator> comparator = Comparators.comparingDouble(keyMapper); return sorted(comparator); } /** * Returns a reverse sorted EntryStream based on the natural ordering of the keys and values. * The entries are sorted first by key in reverse order and then by value in reverse order. * * @return a new EntryStream with entries reverse sorted by key and value * @deprecated replaced by {@link #reverseSorted(Comparator)} */ @Override @Deprecated public EntryStream reverseSorted() { @SuppressWarnings("rawtypes") final Comparator> cmp = Comparators.reverseOrder(Comparators. comparingByKey((Comparator) Comparators.naturalOrder()) .thenComparing(Comparators.comparingByValue((Comparator) Comparators.naturalOrder()))); return of(_stream.sorted(cmp)); } /** * Returns a reverse sorted EntryStream based on the specified comparator. * The entries are sorted according to the reverse order induced by the specified comparator. * * @param comparator the comparator to compare the entries * @return a new EntryStream with entries reverse sorted by the specified comparator */ @ParallelSupported @IntermediateOp @TerminalOpTriggered public EntryStream reverseSorted(final Comparator> comparator) { return of(_stream.reverseSorted(comparator)); } /** * Returns a reverse sorted EntryStream based on the specified key extractor function. * The entries are sorted according to the reverse order induced by the extracted keys. * * @param keyMapper the function to extract the key for comparison * @return a new EntryStream with entries reverse sorted by the extracted keys */ @ParallelSupported @IntermediateOp @TerminalOpTriggered public EntryStream reverseSortedBy(@SuppressWarnings("rawtypes") final Function, ? extends Comparable> keyMapper) { return of(_stream.reverseSortedBy(keyMapper)); } /** * Returns a stream of indexed entries from this EntryStream. * Each element in the stream is an Indexed object containing the index and the entry. * * @return a Stream of Indexed objects containing the index and the entry */ @Override public Stream>> indexed() { return _stream.indexed(); } /** * Returns a stream consisting of the distinct elements of this EntryStream. * This is a stateful intermediate operation. * * @return a new EntryStream with distinct elements * @see Stream#distinct() */ @Override public EntryStream distinct() { return of(_stream.distinct()); } /** * Returns a stream consisting of the distinct elements of this stream, * The merge function is used to resolve conflicts between duplicate elements. * * @param mergeFunction the function to merge duplicate elements * @return a new EntryStream with distinct elements * @see Stream#distinct(BinaryOperator) */ @ParallelSupported @IntermediateOp @TerminalOpTriggered public EntryStream distinct(final BinaryOperator> mergeFunction) { return of(_stream.distinct(mergeFunction)); } // /** // * // * @param occurrencesFilter // * @return // */ // @ParallelSupported // @IntermediateOp // @TerminalOpTriggered // public EntryStream distinct(final Predicate occurrencesFilter) { // return of(_stream.distinct(occurrencesFilter)); // } /** * Returns a stream consisting of the distinct elements of this stream based on the keys. * The order of the elements is preserved. * * @return a new EntryStream with distinct elements based on the keys * @see Stream#distinctBy(Function) */ @SequentialOnly @IntermediateOp public EntryStream distinctByKey() { final Function, K> keyMapper = Fn.key(); if (isParallel()) { return of(_stream.sequential() .distinctBy(keyMapper) .parallel(_stream.maxThreadNum(), _stream.executorNumForVirtualThread(), _stream.splitor(), _stream.asyncExecutor(), _stream.cancelUncompletedThreads())); } else { return of(_stream.distinctBy(keyMapper)); } } /** * Returns a stream consisting of the distinct elements of this stream based on the values. * The order of the elements is preserved. * * @return a new EntryStream with distinct elements based on the values * @see Stream#distinctBy(Function) */ @SequentialOnly @IntermediateOp public EntryStream distinctByValue() { final Function, V> keyMapper = Fn.value(); if (isParallel()) { return of(_stream.sequential() .distinctBy(keyMapper) .parallel(_stream.maxThreadNum(), _stream.executorNumForVirtualThread(), _stream.splitor(), _stream.asyncExecutor(), _stream.cancelUncompletedThreads())); } else { return of(_stream.distinctBy(keyMapper)); } } /** * Returns a stream consisting of the distinct elements of this stream based on the keys extracted by the specified key extractor function. * The order of the elements is preserved. * * @param keyMapper the function to extract the key for comparison * @return a new EntryStream with distinct elements based on the extracted keys * @see Stream#distinctBy(Function) */ @ParallelSupported @IntermediateOp public EntryStream distinctBy(final Function, ?> keyMapper) { return of(_stream.distinctBy(keyMapper)); } /** * Returns a stream consisting of the distinct elements of this stream based on the keys extracted by the specified key extractor function. * The merge function is used to resolve conflicts between duplicate elements. * * @param keyMapper the function to extract the key for comparison * @param mergeFunction the function to merge duplicate elements * @return a new EntryStream with distinct elements based on the extracted keys * @see Stream#distinctBy(Function, BinaryOperator) */ @ParallelSupported @IntermediateOp @TerminalOpTriggered public EntryStream distinctBy(final Function, ?> keyMapper, final BinaryOperator> mergeFunction) { return of(_stream.distinctBy(keyMapper, mergeFunction)); } // /** // * // * @param keyMapper // * @param occurrencesFilter // * @return // * @see #groupBy(Function, Collector) // */ // @ParallelSupported // @IntermediateOp // @TerminalOpTriggered // public EntryStream distinctBy(final Function,?> keyMapper, // final Predicate>, Integer>> occurrencesFilter) { // return of(_stream.distinctBy(keyMapper, occurrencesFilter)); // } // /** // * Distinct by the key extracted by {@code keyMapper} and limit the appearance of the elements with same key to the number calculated by {@code limit} // * // * @param keyMapper // * @param limit // * @return // * @see #groupBy(Function, Collector) // */ // @Beta // @ParallelSupported // @IntermediateOp // @TerminalOpTriggered // public EntryStream distinctLimitBy(final Function, ?> keyMapper, // final BiFunction>, Integer> limit) { // return of(_stream.distinctLimitBy(keyMapper, limit)); // } /** * Returns a new EntryStream with the elements rotated by the specified distance. * Positive values rotate the elements to the right, while negative values rotate them to the left. * * @param distance the distance to rotate the elements * @return a new EntryStream with the elements rotated by the specified distance * @see Stream#rotated(int) */ @Override public EntryStream rotated(final int distance) { return of(_stream.rotated(distance)); } /** * Returns a new EntryStream with the elements shuffled randomly. * * @return a new EntryStream with the elements shuffled * @see Stream#shuffled() */ @Override public EntryStream shuffled() { return of(_stream.shuffled()); } /** * Returns a new EntryStream with the elements shuffled using the specified random. * * @param rnd the random to shuffle the elements * @return a new EntryStream with the elements shuffled using the specified random * @see Stream#shuffled(Random) */ @Override public EntryStream shuffled(final Random rnd) { return of(_stream.shuffled(rnd)); } /** * Returns a new EntryStream with the elements in reverse order. * * @return a new EntryStream with the elements reversed * @see Stream#reversed() */ @Override public EntryStream reversed() { return of(_stream.reversed()); } /** * Returns a new EntryStream with the elements cycled. * The stream will repeat its elements indefinitely. * * @return a new EntryStream with the elements cycled * @see Stream#cycled() */ @Override public EntryStream cycled() { return of(_stream.cycled()); } /** * Returns a new EntryStream with the elements cycled a specified number of times. * * @param rounds the number of rounds to cycle the elements * @return a new EntryStream with the elements cycled the specified number of times * @see Stream#cycled(long) */ @Override public EntryStream cycled(final long rounds) { return of(_stream.cycled(rounds)); } /** * Prepends the specified map to the current EntryStream. * If the map is empty, the original stream is returned. * * @param the type of the map to prepend * @param map the map to prepend to the stream * @return a new EntryStream with the elements of the specified map prepended * @see Stream#prepend(Collection) */ @SequentialOnly @IntermediateOp @SuppressWarnings("rawtypes") public > EntryStream prepend(final M map) { if (N.isEmpty(map)) { return of(_stream); } final Set> set = (Set) map.entrySet(); return of(_stream.prepend(set)); } /** * Prepends the specified stream to the current EntryStream. * * @param stream the stream to prepend to the current stream * @return a new EntryStream with the elements of the specified stream prepended * @see Stream#prepend(Stream) */ @Override public EntryStream prepend(final EntryStream stream) { return of(_stream.prepend(stream._stream)); } /** * Prepends the specified optional entry to the current EntryStream. * If the optional entry is empty, the original stream is returned. * * @param op the optional entry to prepend to the stream * @return a new EntryStream with the optional entry prepended * @see Stream#prepend(Optional) */ @Override public EntryStream prepend(final Optional> op) { if (op.isEmpty()) { return this; } return of(_stream.prepend(op)); } /** * Appends the specified map to the current EntryStream. * If the map is empty, the original stream is returned. * * @param the type of the map to append * @param map the map to append to the stream * @return a new EntryStream with the elements of the specified map appended * @see Stream#append(Collection) */ @SequentialOnly @IntermediateOp @SuppressWarnings("rawtypes") public > EntryStream append(final M map) { if (N.isEmpty(map)) { return of(_stream); } final Set> set = (Set) map.entrySet(); return of(_stream.append(set)); } /** * Appends the specified stream to the current EntryStream. * * @param stream the stream to append to the current stream * @return a new EntryStream with the elements of the specified stream appended * @see Stream#append(Stream) */ @Override public EntryStream append(final EntryStream stream) { return of(_stream.append(stream._stream)); } /** * Appends the specified optional entry to the current EntryStream. * If the optional entry is empty, the original stream is returned. * * @param op the optional entry to append to the stream * @return a new EntryStream with the optional entry appended * @see Stream#append(Optional) */ @Override public EntryStream append(final Optional> op) { if (op.isEmpty()) { return this; } return of(_stream.append(op)); } /** * Appends the specified map to the current EntryStream if the stream is empty. * If the map is empty or the stream is not empty, the original stream is returned. * * @param the type of the map to append * @param map the map to append to the stream if the stream is empty * @return a new EntryStream with the elements of the specified map appended if the stream is empty * @see Stream#appendIfEmpty(Collection) */ @SequentialOnly @IntermediateOp @SuppressWarnings("rawtypes") public > EntryStream appendIfEmpty(final M map) { if (N.isEmpty(map)) { return of(_stream); } final Set> set = (Set) map.entrySet(); return of(_stream.appendIfEmpty(set)); } /** * Appends the specified EntryStream to the current EntryStream if the stream is empty. * If the stream is not empty, the original stream is returned. * * @param supplier the supplier providing the EntryStream to append if the current stream is empty * @return a new EntryStream with the elements of the specified EntryStream appended if the current stream is empty * @see Stream#appendIfEmpty(Supplier) */ @Override public EntryStream appendIfEmpty(final Supplier> supplier) { return EntryStream.of(_stream.appendIfEmpty(() -> supplier.get()._stream)); } /** * Executes the specified action if the stream is empty. * * @param action the action to execute if the stream is empty * @return a new EntryStream with the action executed if the stream is empty * @throws IllegalStateException if the action cannot be executed * @see Stream#ifEmpty(Runnable) */ @Override public EntryStream ifEmpty(final Runnable action) throws IllegalStateException { return EntryStream.of(_stream.ifEmpty(action)); } /** * Skips the first n elements of this EntryStream. * * @param n the number of elements to skip * @return a new EntryStream with the first n elements skipped * @see Stream#skip(long) */ @SequentialOnly @IntermediateOp @Override public EntryStream skip(final long n) { return of(_stream.skip(n)); } /** * Skips the first n elements of this EntryStream and applies the specified consumer to each skipped element. * * @param n the number of elements to skip * @param actionOnSkippedItem the consumer to apply to each skipped element * @return a new EntryStream with the first n elements skipped * @see Stream#skip(long, Consumer) */ @Override public EntryStream skip(final long n, final Consumer> actionOnSkippedItem) { return of(_stream.skip(n, actionOnSkippedItem)); } /** * Limits the number of elements in this EntryStream to the specified maximum size. * * @param maxSize the maximum number of elements to include in the stream * @return a new EntryStream with at most maxSize elements */ @SequentialOnly @IntermediateOp @Override public EntryStream limit(final long maxSize) { return of(_stream.limit(maxSize)); } // /** // * // * @param from // * @param to // * @return // * @deprecated // */ // @Deprecated // @SequentialOnly // public EntryStream slice(final long from, final long to) { // return of(s.slice(from, to)); // } /** * Returns a new EntryStream with entries selected at regular intervals. * The step parameter determines the interval between entries in the resulting stream. * For example, a step of 2 will include every second entry from the original stream. * * @param step the interval between elements to include in the resulting stream * @return A new EntryStream consisting of every 'step'th entry of this stream. * @see Stream#step(long) */ @Override public EntryStream step(final long step) { return of(_stream.step(step)); } /** * Limits the rate at which elements are processed in this EntryStream. * The rateLimiter parameter controls the rate of processing. * * @param rateLimiter the RateLimiter to control the rate of processing * @return a new EntryStream with rate-limited processing * @see Stream#rateLimited(RateLimiter) */ @Override public EntryStream rateLimited(final RateLimiter rateLimiter) { return of(_stream.rateLimited(rateLimiter)); } /** * Delays each element in this EntryStream by the given duration except for the first element. * * @param duration the duration to delay each element * @return a new EntryStream with delayed processing * @see Stream#delay(Duration) */ @Override public EntryStream delay(final Duration duration) { return of(_stream.delay(duration)); } /** * Performs the provided action on the entries pulled by downstream/terminal operation. * Mostly, it's used for debugging. * This is an intermediate operation. * * @param action The action to be performed on the entries pulled by downstream/terminal operation * @return A new EntryStream consisting of the elements of this stream with the provided action applied to each element. * @see Stream#peek(Consumer) */ @Override public EntryStream peek(final Consumer> action) { return of(_stream.peek(action)); } /** * Performs the provided action on the entries pulled by downstream/terminal operation. * Mostly, it's used for debugging. * This is an intermediate operation. * * @param action The action to be performed on the entries pulled by downstream/terminal operation * @return A new EntryStream consisting of the elements of this stream with the provided action applied to each element. * @see Stream#peek(Consumer) */ @ParallelSupported @IntermediateOp public EntryStream peek(final BiConsumer action) { return of(_stream.peek(Fn.Entries.c(action))); } /** * Performs the provided action on the entries pulled by downstream/terminal operation. * * @param action The action to be performed on the entries pulled by downstream/terminal operation * @return A new EntryStream consisting of the elements of this stream with the provided action applied to each element. * @see Stream#onEach(Consumer) */ @Override public EntryStream onEach(final Consumer> action) { return of(_stream.onEach(action)); } /** * Performs the provided action on the entries pulled by downstream/terminal operation. * * @param action The action to be performed on the entries pulled by downstream/terminal operation * @return A new EntryStream consisting of the elements of this stream with the provided action applied to each element. * @see Stream#onEach(Consumer) */ @ParallelSupported @IntermediateOp public EntryStream onEach(final BiConsumer action) { return of(_stream.onEach(Fn.Entries.c(action))); } /** * Performs the provided action on each entry of the EntryStream. * * @param the type of exception that may be thrown by the action * @param action the action to be performed for each entry * @throws E if the action throws an exception * @see Stream#forEach(Consumer) */ @ParallelSupported @TerminalOp public void forEach(final Throwables.Consumer, E> action) throws E { _stream.forEach(action); } /** * Performs the provided action on each entry of the EntryStream. * * @param the type of exception that may be thrown by the action * @param action the action to be performed for each entry * @throws E if the action throws an exception * @see Stream#forEach(Throwables.Consumer) */ @ParallelSupported @TerminalOp public void forEach(final Throwables.BiConsumer action) throws E { _stream.forEach(Fn.Entries.ec(action)); } /** * Performs the provided action on each entry of the EntryStream with its index. * * @param the type of exception that may be thrown by the action * @param action the action to be performed for each entry with its index * @throws E if the action throws an exception * @see Stream#forEachIndexed(Throwables.IntObjConsumer) */ @ParallelSupported @TerminalOp public void forEachIndexed(final Throwables.IntObjConsumer, E> action) throws E { _stream.forEachIndexed(action); } /** * Returns an Optional containing the minimum entry of this EntryStream according to the provided comparator. * * @param comparator the comparator to compare the entries * @return an Optional containing the minimum entry of this EntryStream, or an empty Optional if the stream is empty * @see Stream#min(Comparator) */ @ParallelSupported @TerminalOp public Optional> min(final Comparator> comparator) { return _stream.min(comparator); } /** * Returns an Optional containing the minimum entry of this EntryStream according to the provided key comparator. * * @param keyComparator the comparator to compare the keys * @return an Optional containing the minimum entry of this EntryStream, or an empty Optional if the stream is empty * @see Stream#min(Comparator) */ @ParallelSupported @TerminalOp public Optional> minByKey(final Comparator keyComparator) { return _stream.min(Comparators.comparingBy(Fn.key(), keyComparator)); } /** * Returns an Optional containing the minimum entry of this EntryStream according to the provided value comparator. * * @param valueComparator the comparator to compare the values * @return an Optional containing the minimum entry of this EntryStream, or an empty Optional if the stream is empty * @see Stream#min(Comparator) */ @ParallelSupported @TerminalOp public Optional> minByValue(final Comparator valueComparator) { return _stream.min(Comparators.comparingBy(Fn.value(), valueComparator)); } /** * Returns an Optional containing the minimum entry of this EntryStream based on the natural ordering of the keys extracted by the key mapper. Nulls are considered bigger than non-nulls here * * @param keyMapper the function to extract the key for comparison * @return an Optional containing the minimum entry of this EntryStream, or an empty Optional if the stream is empty * @see Stream#minBy(Function) */ @ParallelSupported @TerminalOp @SuppressWarnings("rawtypes") public Optional> minBy(final Function, ? extends Comparable> keyMapper) { return _stream.minBy(keyMapper); } /** * Returns an Optional containing the maximum entry of this EntryStream according to the provided comparator. * * @param comparator the comparator to compare the entries * @return an Optional containing the maximum entry of this EntryStream, or an empty Optional if the stream is empty * @see Stream#max(Comparator) */ @ParallelSupported @TerminalOp public Optional> max(final Comparator> comparator) { return _stream.max(comparator); } /** * Returns an Optional containing the maximum entry of this EntryStream according to the provided key comparator. * * @param keyComparator the comparator to compare the keys * @return an Optional containing the maximum entry of this EntryStream, or an empty Optional if the stream is empty * @see Stream#max(Comparator) */ @ParallelSupported @TerminalOp public Optional> maxByKey(final Comparator keyComparator) { return _stream.max(Comparators.comparingBy(Fn.key(), keyComparator)); } /** * Returns an Optional containing the maximum entry of this EntryStream according to the provided value comparator. * * @param valueComparator the comparator to compare the values * @return an Optional containing the maximum entry of this EntryStream, or an empty Optional if the stream is empty * @see Stream#max(Comparator) */ @ParallelSupported @TerminalOp public Optional> maxByValue(final Comparator valueComparator) { return _stream.max(Comparators.comparingBy(Fn.value(), valueComparator)); } /** * Returns an Optional containing the maximum entry of this EntryStream based on the natural ordering of the keys extracted by the key mapper. Nulls are considered smaller than non-nulls here * * @param keyMapper the function to extract the key for comparison * @return an Optional containing the maximum entry of this EntryStream, or an empty Optional if the stream is empty * @see Stream#maxBy(Function) */ @ParallelSupported @TerminalOp @SuppressWarnings("rawtypes") public Optional> maxBy(final Function, ? extends Comparable> keyMapper) { return _stream.maxBy(keyMapper); } /** * Checks if any elements of this EntryStream match the provided predicate. * * @param the type of exception that may be thrown by the predicate * @param predicate the predicate to test the elements of this stream * @return {@code true} if any elements match the predicate, otherwise false * @throws E if the predicate throws an exception * @see Stream#anyMatch(Predicate) */ @ParallelSupported @TerminalOp public boolean anyMatch(final Throwables.Predicate, E> predicate) throws E { return _stream.anyMatch(predicate); } /** * Checks if any elements of this EntryStream match the provided predicate. * * @param the type of exception that may be thrown by the predicate * @param predicate the predicate to test the elements of this stream * @return {@code true} if any elements match the predicate, otherwise false * @throws E if the predicate throws an exception * @see Stream#anyMatch(Predicate) */ @ParallelSupported @TerminalOp public boolean anyMatch(final Throwables.BiPredicate predicate) throws E { return _stream.anyMatch(Fn.Entries.ep(predicate)); } /** * Checks if all elements of this EntryStream match the provided predicate. * * @param the type of exception that may be thrown by the predicate * @param predicate the predicate to test the elements of this stream * @return {@code true} if all elements match the predicate or this EntryStream is empty, otherwise false * @throws E if the predicate throws an exception * @see Stream#allMatch(Predicate) */ @ParallelSupported @TerminalOp public boolean allMatch(final Throwables.Predicate, E> predicate) throws E { return _stream.allMatch(predicate); } /** * Checks if all elements of this EntryStream match the provided predicate. * * @param the type of exception that may be thrown by the predicate * @param predicate the predicate to test the elements of this stream * @return {@code true} if all elements match the predicate or this EntryStream is empty, otherwise false * @throws E if the predicate throws an exception * @see Stream#allMatch(Predicate) */ @ParallelSupported @TerminalOp public boolean allMatch(final Throwables.BiPredicate predicate) throws E { return _stream.allMatch(Fn.Entries.ep(predicate)); } /** * Checks if no elements of this EntryStream match the provided predicate. * * @param the type of exception that may be thrown by the predicate * @param predicate the predicate to test the elements of this stream * @return {@code true} if no elements match the predicate or this EntryStream is empty, otherwise false * @throws E if the predicate throws an exception * @see Stream#noneMatch(Predicate) */ @ParallelSupported @TerminalOp public boolean noneMatch(final Throwables.Predicate, E> predicate) throws E { return _stream.noneMatch(predicate); } /** * Checks if no elements of this EntryStream match the provided predicate. * * @param the type of exception that may be thrown by the predicate * @param predicate the predicate to test the elements of this stream * @return {@code true} if no elements match the predicate or this EntryStream is empty, otherwise false * @throws E if the predicate throws an exception * @see Stream#noneMatch(Predicate) */ @ParallelSupported @TerminalOp public boolean noneMatch(final Throwables.BiPredicate predicate) throws E { return _stream.noneMatch(Fn.Entries.ep(predicate)); } /** * Checks if the specified number of elements in this sequence match the provided predicate. *
* The operation stops as soon as the number of elements matching the predicate is bigger than {@code atMost}. * @implNote it's equivalent to {@code {@code atLeast} <= stream.filter(predicate).limit(atMost + 1).count() <= atMost} * * @param the type of the exception that can be thrown when processing elements in the EntryStream * @param {@code atLeast} the minimum number of elements that need to match the predicate * @param {@code atMost} the maximum number of elements that need to match the predicate * @param predicate a non-interfering, stateless predicate to apply to each element to determine if it should be counted * @return {@code true} if the number of elements matching the predicate is within the specified range (inclusive), {@code false} otherwise * @throws E if any element processing results in an exception * @see Stream#nMatch(long, long, Throwables.Predicate) */ @ParallelSupported @TerminalOp public boolean nMatch(final long atLeast, final long atMost, final Throwables.Predicate, E> predicate) throws E { return _stream.nMatch(atLeast, atMost, predicate); } /** * Checks if the specified number of elements in this sequence match the provided predicate. *
* The operation stops as soon as the number of elements matching the predicate is bigger than {@code atMost}. * @implNote it's equivalent to {@code {@code atLeast} <= stream.filter(predicate).limit(atMost + 1).count() <= atMost} * * @param the type of the exception that can be thrown when processing elements in the EntryStream * @param {@code atLeast} the minimum number of elements that need to match the predicate * @param {@code atMost} the maximum number of elements that need to match the predicate * @param predicate a non-interfering, stateless predicate to apply to each element to determine if it should be counted * @return {@code true} if the number of elements matching the predicate is within the specified range (inclusive), {@code false} otherwise * @throws E if any element processing results in an exception * @see Stream#nMatch(long, long, Throwables.Predicate) */ @ParallelSupported @TerminalOp public boolean nMatch(final long atLeast, final long atMost, final Throwables.BiPredicate predicate) throws E { return _stream.nMatch(atLeast, atMost, Fn.Entries.ep(predicate)); } /** * Finds the first entry in this EntryStream that matches the provided predicate. * * @param the type of exception that may be thrown by the predicate * @param predicate the predicate to test the elements of this stream * @return an Optional containing the first entry that matches the predicate, or an empty Optional if no match is found * @throws E if the predicate throws an exception * @see Stream#findFirst(Throwables.Predicate) */ @ParallelSupported @TerminalOp public Optional> findFirst(final Throwables.Predicate, E> predicate) throws E { return _stream.findFirst(predicate); } /** * Finds the first entry in this EntryStream that matches the provided predicate. * * @param the type of exception that may be thrown by the predicate * @param predicate the predicate to test the elements of this stream * @return an Optional containing the first entry that matches the predicate, or an empty Optional if no match is found * @throws E if the predicate throws an exception * @see Stream#findFirst(Throwables.Predicate) */ @ParallelSupported @TerminalOp public Optional> findFirst(final Throwables.BiPredicate predicate) throws E { return _stream.findFirst(Fn.Entries.ep(predicate)); } /** * Finds any entry in this EntryStream that matches the provided predicate. * * @param the type of exception that may be thrown by the predicate * @param predicate the predicate to test the elements of this stream * @return an Optional containing any entry that matches the predicate, or an empty Optional if no match is found * @throws E if the predicate throws an exception * @see Stream#findAny(Throwables.Predicate) */ @ParallelSupported @TerminalOp public Optional> findAny(final Throwables.Predicate, E> predicate) throws E { return _stream.findAny(predicate); } /** * Finds any entry in this EntryStream that matches the provided predicate. * * @param the type of exception that may be thrown by the predicate * @param predicate the predicate to test the elements of this stream * @return an Optional containing any entry that matches the predicate, or an empty Optional if no match is found * @throws E if the predicate throws an exception * @see Stream#findAny(Throwables.Predicate) */ @ParallelSupported @TerminalOp public Optional> findAny(final Throwables.BiPredicate predicate) throws E { return _stream.findAny(Fn.Entries.ep(predicate)); } /** * Finds the last entry in this EntryStream that matches the provided predicate. * * @param the type of exception that may be thrown by the predicate * @param predicate the predicate to test the elements of this stream * @return an Optional containing the last entry that matches the predicate, or an empty Optional if no match is found * @throws E if the predicate throws an exception * @see Stream#findLast(Throwables.Predicate) */ @Beta @ParallelSupported @TerminalOp public Optional> findLast(final Throwables.Predicate, E> predicate) throws E { return _stream.findLast(predicate); } /** * Finds the last entry in this EntryStream that matches the provided predicate. * * @param the type of exception that may be thrown by the predicate * @param predicate the predicate to test the elements of this stream * @return an Optional containing the last entry that matches the predicate, or an empty Optional if no match is found * @throws E if the predicate throws an exception * @see Stream#findLast(Throwables.Predicate) */ @Beta @ParallelSupported @TerminalOp public Optional> findLast(final Throwables.BiPredicate predicate) throws E { return _stream.findLast(Fn.Entries.ep(predicate)); } // /** // * Returns the first element matched by {@code predicateForFirst} if found or the first element if this stream is not empty., // * Otherwise, an empty {@code Optional>} will be returned. // * // * @param // * @param predicate // * @return // * @throws E // */ // @ParallelSupported // @TerminalOp // public Optional> findFirstOrElseAny(final Throwables.Predicate, E> predicate) throws E { // return _stream.findFirstOrElseAny(predicate); // } // // /** // * Returns the first element matched by {@code predicateForFirst} if found or the first element if this stream is not empty. // * Otherwise, an empty {@code Optional>} will be returned. // * // * @param // * @param predicate // * @return // * @throws E // */ // @ParallelSupported // @TerminalOp // public Optional> findFirstOrElseAny(final Throwables.BiPredicate predicate) throws E { // return _stream.findFirstOrElseAny(Fn.Entries.ep(predicate)); // } // // /** // * Returns the first element matched by {@code predicateForFirst} if found or the last element if this stream is not empty. // * Otherwise, an empty {@code Optional>} will be returned. // * // * @param // * @param predicate // * @return // * @throws E // */ // @ParallelSupported // @TerminalOp // public Optional> findFirstOrElseLast(final Throwables.Predicate, E> predicate) throws E { // return _stream.findFirstOrElseLast(predicate); // } // // /** // * Returns the first element matched by {@code predicateForFirst} if found or the last element if this stream is not empty. // * Otherwise, an empty {@code Optional>} will be returned. // * // * @param // * @param predicate // * @return // * @throws E // */ // @ParallelSupported // @TerminalOp // public Optional> findFirstOrElseLast(final Throwables.BiPredicate predicate) throws E { // return _stream.findFirstOrElseLast(Fn.Entries.ep(predicate)); // } /** * Returns an Optional containing the first entry of this EntryStream. * * @return an Optional containing the first entry, or an empty Optional if the stream is empty * @see Stream#first() */ @Override public Optional> first() { return _stream.first(); } /** * Returns an Optional containing the last entry of this EntryStream. * * @return an Optional containing the last entry, or an empty Optional if the stream is empty * @see Stream#last() */ @Override public Optional> last() { return _stream.last(); } /** * Returns the entry at the specified position in this stream. * The position is zero-based, meaning the first entry in the stream has a position of 0, the second has a position of 1, and so on. * * @param position The position of the entry to return. * @return An Optional containing the entry at the specified position in this stream if it exists, otherwise an empty Optional. * @see Stream#elementAt(long) */ @Override public Optional> elementAt(final long position) { return _stream.elementAt(position); } /** * Returns an {@code Optional} containing the only entry of this EntryStream if it contains exactly one entry, or an empty {@code Optional} if the EntryStream is empty * If the EntryStream contains more than one entry, an exception is thrown. * * @return an Optional containing the only entry of this EntryStream if it is not empty, otherwise an empty Optional * @throws TooManyElementsException if the EntryStream contains more than one entry * @see Stream#onlyOne() */ @Override public Optional> onlyOne() throws TooManyElementsException { return _stream.onlyOne(); } /** * Calculates the percentiles of the entries in the stream. * All elements will be loaded into memory and sorted if not yet. * The returned map contains the percentile values as keys and the corresponding elements as values. * * @return * @deprecated replaced by {@link #percentiles(Comparator)} * @see N#percentiles(int[]) */ @Override @Deprecated public Optional>> percentiles() { return _stream.percentiles(); } /** * Calculates the percentiles of the entries in the stream based on the specified comparator. * All elements will be loaded into memory and sorted if not yet. * The returned map contains the percentile values as keys and the corresponding elements as values. * * @param comparator the comparator to determine the order of the entries * @return an Optional containing a map of percentiles to entries, or an empty Optional if the stream is empty * @see N#percentiles(int[]) */ public Optional>> percentiles(final Comparator> comparator) { return _stream.percentiles(comparator); } /** * Returns the count of elements in this EntryStream. * * @return the number of elements in this EntryStream * @see Stream#count() */ @Override public long count() { return _stream.count(); } /** * Returns an iterator over the elements in this EntryStream. * * Remember to close this Stream after the iteration is done, if needed. * * @return an iterator over the elements in this EntryStream * @see Stream#iterator() */ @Override public ObjIterator> iterator() { return _stream.iteratorEx(); } /** * Returns a BiIterator over the elements in this EntryStream. * Remember to close this Stream after the iteration is done, if needed. * * @return a BiIterator over the elements in this EntryStream */ @SequentialOnly public BiIterator biIterator() { final ObjIterator> iter = _stream.iteratorEx(); final BooleanSupplier hasNext = iter::hasNext; final Consumer> output = new Consumer<>() { private Map.Entry entry = null; @Override public void accept(final Pair t) { entry = iter.next(); t.set(entry.getKey(), entry.getValue()); } }; return BiIterator.generate(hasNext, output); } /** * Converts the elements of this stream to an array. * * @param closeStream whether to close the stream after conversion * @return an array containing the elements of this stream */ @Override protected Object[] toArray(final boolean closeStream) { return _stream.toArray(closeStream); } /** * Returns a list containing the elements of this stream. * * @return a List containing the elements of this stream * @see Stream#toList() */ @Override public List> toList() { return _stream.toList(); } /** * Returns a set containing the elements of this stream. * * @return a Set containing the elements of this stream * @see Stream#toSet() */ @Override public Set> toSet() { return _stream.toSet(); } /** * Returns a collection containing the elements of this stream. * * @param the type of the collection * @param supplier the supplier providing the collection * @return a collection containing the elements of this stream * @see Stream#toCollection(Supplier) */ @Override public >> C toCollection(final Supplier supplier) { return _stream.toCollection(supplier); } /** * Returns a Multiset containing the elements of this stream. * * @return a Multiset containing the elements of this stream * @see Stream#toMultiset() */ @Override public Multiset> toMultiset() { return _stream.toMultiset(); } /** * Returns a Multiset containing the elements of this stream. * * @param supplier a supplier providing the Multiset * @return a Multiset containing the elements of this stream * @see Stream#toMultiset(Supplier) */ @Override public Multiset> toMultiset(final Supplier>> supplier) { return _stream.toMultiset(supplier); } /** * Converts the elements of this stream to a Map where each key is associated with a single value. * * @return a Map containing the elements of this stream * @throws IllegalStateException if there are duplicated keys * @see Stream#toMap(Throwables.Function, Throwables.Function) * @see Fn#throwingMerger() * @see Fn#replacingMerger() * @see Fn#ignoringMerger() */ @SequentialOnly public Map toMap() throws IllegalStateException { if (isParallel()) { return _stream.sequential().toMap(Fn.key(), Fn.value()); } else { return _stream.toMap(Fn.key(), Fn.value()); } } /** * Converts the elements of this stream to a Map where each key is associated with a single value, * which is the result of applying the merge function to all values associated with that key. * * @param mergeFunction the function to merge values associated with the same key * @return a Map containing the elements of this stream * @see Stream#toMap(Throwables.Function, Throwables.Function, BinaryOperator) * @see Fn#throwingMerger() * @see Fn#replacingMerger() * @see Fn#ignoringMerger() */ @SequentialOnly @TerminalOp public Map toMap(final BinaryOperator mergeFunction) { if (isParallel()) { return _stream.sequential().toMap(Fn.key(), Fn.value(), mergeFunction); } else { return _stream.toMap(Fn.key(), Fn.value(), mergeFunction); } } /** * Converts the elements of this stream to a Map where each key is associated with a single value. * * @param mapFactory The supplier providing a new empty Map into which the results will be inserted. * @return a Map containing the elements of this stream * @throws IllegalStateException if there are duplicated keys * @see Stream#toMap(Throwables.Function, Throwables.Function, Supplier) * @see Fn#throwingMerger() * @see Fn#replacingMerger() * @see Fn#ignoringMerger() */ @SequentialOnly @TerminalOp public > M toMap(final Supplier mapFactory) throws IllegalStateException { if (isParallel()) { return _stream.sequential().toMap(Fn.key(), Fn.value(), mapFactory); } else { return _stream.toMap(Fn.key(), Fn.value(), mapFactory); } } /** * Converts the elements of this stream to a Map where each key is associated with a single value, * which is the result of applying the merge function to all values associated with that key. * * @param mergeFunction the function to merge values associated with the same key * @param mapFactory The supplier providing a new empty Map into which the results will be inserted. * @return a Map containing the elements of this stream * @see Stream#toMap(Throwables.Function, Throwables.Function, BinaryOperator, Supplier) * @see Fn#throwingMerger() * @see Fn#replacingMerger() * @see Fn#ignoringMerger() */ @SequentialOnly @TerminalOp public > M toMap(final BinaryOperator mergeFunction, final Supplier mapFactory) { if (isParallel()) { return _stream.sequential().toMap(Fn.key(), Fn.value(), mergeFunction, mapFactory); } else { return _stream.toMap(Fn.key(), Fn.value(), mergeFunction, mapFactory); } } /** * Converts the elements of this stream to a Map where each key is associated with a single value and then applies the provided function to the resulting Map. * * @param the type of the result of the function * @param the type of exception that may be thrown by the function * @param func the function to apply to the resulting Map * @return the result of applying the function to the Map * @throws IllegalStateException if there are duplicated keys * @throws E if the function throws an exception * @see Fn#throwingMerger() * @see Fn#replacingMerger() * @see Fn#ignoringMerger() */ @SequentialOnly @TerminalOp public R toMapThenApply(final Throwables.Function, ? extends R, E> func) throws IllegalStateException, E { return func.apply(toMap()); } /** * Converts the elements of this stream to a Map where each key is associated with a single value and then applies the provided consumer to the resulting Map. * * @param the type of exception that may be thrown by the consumer * @param consumer the consumer to accept the resulting Map * @throws IllegalStateException if there are duplicated keys * @throws E if the consumer throws an exception * @see Fn#throwingMerger() * @see Fn#replacingMerger() * @see Fn#ignoringMerger() */ @SequentialOnly @TerminalOp public void toMapThenAccept(final Throwables.Consumer, E> consumer) throws IllegalStateException, E { consumer.accept(toMap()); } /** * Converts the elements of this stream to an ImmutableMap where each key is associated with a single value. * * @return an ImmutableMap containing the elements of this stream * @throws IllegalStateException if there are duplicated keys * @see Stream#toImmutableMap(Throwables.Function, Throwables.Function) * @see Fn#throwingMerger() * @see Fn#replacingMerger() * @see Fn#ignoringMerger() */ @SequentialOnly @TerminalOp public ImmutableMap toImmutableMap() throws IllegalStateException { return ImmutableMap.wrap(toMap()); } /** * Converts the elements of this stream to an ImmutableMap where each key is associated with a single value, * which is the result of applying the merge function to all values associated with that key. * * @param mergeFunction the function to merge values associated with the same key * @return an ImmutableMap containing the elements of this stream * @see Stream#toImmutableMap(Throwables.Function, Throwables.Function, BinaryOperator) * @see Fn#throwingMerger() * @see Fn#replacingMerger() * @see Fn#ignoringMerger() */ @SequentialOnly @TerminalOp public ImmutableMap toImmutableMap(final BinaryOperator mergeFunction) { return ImmutableMap.wrap(toMap(mergeFunction)); } /** * Converts the elements of this stream to a ListMultimap where each key is associated with a list of values. * * @return a ListMultimap containing the elements of this stream * @see Stream#toMultimap(Throwables.Function, Throwables.Function) */ @SequentialOnly @TerminalOp public ListMultimap toMultimap() { if (isParallel()) { return _stream.sequential().toMultimap(Fn.key(), Fn.value()); } else { return _stream.toMultimap(Fn.key(), Fn.value()); } } /** * Converts the elements of this stream to a Multimap where each key is associated with a collection of values. * * @param mapFactory The supplier providing a new empty Multimap into which the results will be inserted. * @return a Multimap containing the elements of this stream * @see Stream#toMultimap(Throwables.Function, Throwables.Function, Supplier) */ @SequentialOnly @TerminalOp public , M extends Multimap> M toMultimap(final Supplier mapFactory) { if (isParallel()) { return _stream.sequential().toMultimap(Fn.key(), Fn.value(), mapFactory); } else { return _stream.toMultimap(Fn.key(), Fn.value(), mapFactory); } } /** * Groups the elements of this stream into a Map where each key is associated with a list of values. * * @return a Map containing the elements of this stream grouped by key * @see Stream#groupTo(Throwables.Function, Throwables.Function); */ @SequentialOnly @TerminalOp public Map> groupTo() { if (isParallel()) { return _stream.sequential().groupTo(Fn.key(), Fn.value()); } else { return _stream.groupTo(Fn.key(), Fn.value()); } } /** * Groups the elements of this stream into a Map where each key is associated with a list of values. * * @param mapFactory The supplier providing a new empty Map into which the results will be inserted. * @return a Map containing the elements of this stream grouped by key * @see Stream#groupTo(Throwables.Function, Throwables.Function, Supplier) */ @SequentialOnly @TerminalOp public >> M groupTo(final Supplier mapFactory) { if (isParallel()) { return _stream.sequential().groupTo(Fn.key(), Fn.value(), mapFactory); } else { return _stream.groupTo(Fn.key(), Fn.value(), mapFactory); } } /** * Groups the elements of this stream into a Map where each key is associated with a list of values, * and then applies the provided function to the resulting Map. * * @param the type of the result of the function * @param the type of exception that may be thrown by the function * @param func the function to apply to the resulting Map * @return the result of applying the function to the Map * @throws E if the function throws an exception */ @SequentialOnly @TerminalOp public R groupToThenApply(final Throwables.Function>, ? extends R, E> func) throws E { return func.apply(groupTo()); } /** * Groups the elements of this stream into a Map where each key is associated with a list of values, * and then applies the provided consumer to the resulting Map. * * @param the type of exception that may be thrown by the consumer * @param consumer the consumer to accept the resulting Map * @throws E if the consumer throws an exception */ @SequentialOnly @TerminalOp public void groupToThenAccept(final Throwables.Consumer>, E> consumer) throws E { consumer.accept(groupTo()); } /** * Performs a reduction on the elements of this stream, using the provided accumulator function, and returns the reduced value. * The accumulator function takes two parameters: the current reduced value (or the initial value for the first element), and the current stream element. * * @param identity the initial value of the reduction operation * @param accumulator the function for combining the current reduced value and the current stream element * @return the result of the reduction * @see Stream#reduce(Object, BinaryOperator) */ @SequentialOnly @TerminalOp public Map.Entry reduce(final Map.Entry identity, final BinaryOperator> accumulator) { return _stream.reduce(identity, accumulator); } /** * Performs a reduction on the elements of this stream, using the provided accumulator function, and returns the reduced value. * The accumulator function takes two parameters: the current reduced value and the current stream element. * * @param accumulator the function for combining the current reduced value and the current stream element * @return an Optional describing the result of the reduction. If the stream is empty, an empty Optional is returned. * @see Stream#reduce(BinaryOperator) */ @ParallelSupported @TerminalOp public Optional> reduce(final BinaryOperator> accumulator) { return _stream.reduce(accumulator); } /** * Performs a mutable reduction operation on the elements of this stream using a collector. * * @param the type of the result * @param supplier a function that provides a new mutable result container * @param accumulator an associative, non-interfering, stateless function for incorporating an additional element into a result container * @param combiner an associative, non-interfering, stateless function for combining two values, which must be compatible with the accumulator function. * It's unnecessary to specify {@code combiner} if {@code R} is a {@code Map/Collection/StringBuilder/Multiset/LongMultiset/Multimap/BooleanList/IntList/.../DoubleList}. * @return the result of the reduction * @see Stream#collect(Supplier, BiConsumer, BiConsumer) */ @ParallelSupported @TerminalOp public R collect(final Supplier supplier, final BiConsumer> accumulator, final BiConsumer combiner) { return _stream.collect(supplier, accumulator, combiner); } /** * Performs a mutable reduction operation on the elements of this stream using a Collector. * *
* Only call this method when the returned type {@code R} is one types: {@code Collection/Map/StringBuilder/Multiset/LongMultiset/Multimap/BooleanList/IntList/.../DoubleList}. * Otherwise, please call {@link #collect(Supplier, BiConsumer, BiConsumer)}. * * @param The type of the result. It must be {@code Collection/Map/StringBuilder/Multiset/LongMultiset/Multimap/BooleanList/IntList/.../DoubleList}. * @param supplier A function that creates a new result container. For a parallel execution, this function may be called multiple times and must return a fresh value each time. * @param accumulator An associative, non-interfering, stateless function for incorporating an additional element into a result. * @throws IllegalArgumentException if the returned type {@code R} is not one of the types: {@code Collection/Map/StringBuilder/Multiset/LongMultiset/Multimap/BooleanList/IntList/.../DoubleList}. * @return the result of the reduction * @see #collect(Supplier, BiConsumer, BiConsumer) * @see #collect(Collector) * @see Stream#collect(Supplier, BiConsumer) */ @ParallelSupported @TerminalOp public R collect(final Supplier supplier, final BiConsumer> accumulator) { return _stream.collect(supplier, accumulator); } /** * Performs a mutable reduction operation on the elements of this stream using a Collector. * * @param the type of the result * @param collector the Collector describing the reduction operation * @return the result of the reduction * @see Stream#collect(Collector) */ @ParallelSupported @TerminalOp public R collect(final Collector, ?, R> collector) { return _stream.collect(collector); } /** * Performs a mutable reduction operation on the elements of this stream using a Collector, * and then applies the provided function to the result of the reduction. * * @param the type of the intermediate result * @param the type of the final result * @param the type of exception that may be thrown by the finisher function * @param downstream the Collector describing the reduction operation * @param func the function to apply to the result of the reduction * @return the result of applying the finisher function to the result of the reduction * @throws E if the finisher function throws an exception * @see Stream#collectThenApply(Collector, Throwables.Function) */ @ParallelSupported @TerminalOp public RR collectThenApply(final Collector, ?, R> downstream, final Throwables.Function func) throws E { return _stream.collectThenApply(downstream, func); } /** * Performs a mutable reduction operation on the elements of this stream using a Collector, * and then applies the provided consumer to the result of the reduction. * * @param the type of the intermediate result * @param the type of exception that may be thrown by the consumer * @param downstream the Collector describing the reduction operation * @param consumer the consumer to accept the result of the reduction * @throws E if the consumer throws an exception * @see Stream#collectThenAccept(Collector, Throwables.Consumer) */ @ParallelSupported @TerminalOp public void collectThenAccept(final Collector, ?, R> downstream, final Throwables.Consumer consumer) throws E { _stream.collectThenAccept(downstream, consumer); } /** * Joins the elements of this stream into a single String with the specified delimiter. * * @param delimiter the delimiter to be used between each element * @return a String containing the elements of this stream separated by the specified delimiter * @see Stream#join(CharSequence) */ @Override public String join(final CharSequence delimiter) { return join(delimiter, "", ""); } /** * Joins the elements of this stream into a single String with the specified delimiter, prefix, and suffix. * * @param delimiter the delimiter to be used between each element * @param prefix the prefix to be added at the beginning * @param suffix the suffix to be added at the end * @return a String containing the elements of this stream separated by the specified delimiter, prefix, and suffix * @see Stream#join(CharSequence, CharSequence, CharSequence) */ @Override public String join(final CharSequence delimiter, final CharSequence prefix, final CharSequence suffix) { return join(delimiter, "=", prefix, suffix); } /** * Joins the elements of this stream into a single String with the specified delimiter and key-value delimiter. * * @param delimiter the delimiter to be used between each element * @param keyValueDelimiter the delimiter to be used between the key and value of each element * @return a String containing the elements of this stream separated by the specified delimiter and key-value delimiter */ @SequentialOnly @TerminalOp public String join(final CharSequence delimiter, final CharSequence keyValueDelimiter) { return join(delimiter, keyValueDelimiter, "", ""); } /** * Joins the elements of this stream into a single String with the specified delimiter and key-value delimiter, prefix, and suffix. * * @param delimiter the delimiter to be used between each element * @param keyValueDelimiter the delimiter to be used between the key and value of each element * @param prefix the prefix to be added at the beginning * @param suffix the suffix to be added at the end * @return a String containing the elements of this stream separated by the specified delimiter, key-value delimiter, prefix, and suffix */ @SequentialOnly @TerminalOp public String join(final CharSequence delimiter, final CharSequence keyValueDelimiter, final CharSequence prefix, final CharSequence suffix) throws IllegalStateException { _stream.assertNotClosed(); try { @SuppressWarnings("resource") final Joiner joiner = Joiner.with(delimiter, keyValueDelimiter, prefix, suffix).reuseCachedBuffer(); final Iterator> iter = _stream.iteratorEx(); while (iter.hasNext()) { joiner.appendEntry(iter.next()); } return joiner.toString(); } finally { close(); } } /** * Joins the elements of this stream into a single String using the provided Joiner. * The Joiner specifies the delimiter, prefix, and suffix to be used for joining. * * @param joiner The Joiner specifying how to join the elements of the stream. * @return The provided Joiner after it has been used to join the elements of the stream. * @see Stream#joinTo(Joiner) */ @Override @TerminalOp public Joiner joinTo(final Joiner joiner) throws IllegalStateException, IllegalArgumentException { _stream.assertNotClosed(); checkArgNotNull(joiner, cs.joiner); try { final Iterator> iter = _stream.iteratorEx(); while (iter.hasNext()) { joiner.appendEntry(iter.next()); } } finally { close(); } return joiner; } // /** // * Transforms the current EntryStream into another EntryStream by applying the provided function. // * The function takes a Stream as input and returns a new Stream. // * The returned Stream is then wrapped into an EntryStream of this class. // * // * @param the type of the keys in the resulting EntryStream // * @param the type of the values in the resulting EntryStream // * @param transfer The function to be applied on the current stream to produce a new stream. // * @return a new EntryStream with the transformed keys and values // * @deprecated Use {@link #transformB(Function>, ? extends Stream>>)} instead // * @see #transformB(Function) // */ // @Deprecated // @Beta // @SequentialOnly // @IntermediateOp // public EntryStream chain( // final Function>, ? extends Stream>> transfer) { // return transformB(transfer); // } /** * Transforms the current EntryStream into another EntryStream by applying the provided function. * The function takes a Stream as input and returns a new Stream. * The returned Stream is then wrapped into an EntryStream of this class. * * @param the type of the keys in the resulting EntryStream * @param the type of the values in the resulting EntryStream * @param transfer The function to be applied on the current stream to produce a new stream. * @return a new EntryStream with the transformed keys and values * @see Stream#transform(Function) * @see Stream#transformB(Function) * @see Stream#transformB(Function, boolean) */ @Beta @SequentialOnly @IntermediateOp public EntryStream transformB( final Function>, ? extends Stream>> transfer) { return transformB(transfer, false); } /** * Transforms the current EntryStream into another EntryStream by applying the provided function. * The function takes a Stream as input and returns a new Stream. * The returned Stream is then wrapped into an EntryStream of this class. * The transformation can be deferred, which means it will be performed when the stream is consumed. * * @param the type of the keys in the resulting EntryStream * @param the type of the values in the resulting EntryStream * @param transfer The function to be applied on the current stream to produce a new stream. * @param deferred If {@code true}, the transformation is deferred until the EntryStream is consumed. * @return A new EntryStream transformed by the provided function. * @see Stream#transform(Function) * @see Stream#transformB(Function) * @see Stream#transformB(Function, boolean) */ @Beta @SequentialOnly @IntermediateOp public EntryStream transformB( final Function>, ? extends Stream>> transfer, final boolean deferred) { assertNotClosed(); checkArgNotNull(transfer, cs.transfer); if (deferred) { final Supplier> delayInitializer = () -> EntryStream.of(transfer.apply(_stream)); return EntryStream.defer(delayInitializer); } else { return of(transfer.apply(_stream)); } } // @SequentialOnly // @IntermediateOp // @Beta // public EntryStream transform(Function, EntryStream> transfer) { // return transfer.apply(this); // } // /** // * // * @param // * @param // * @param terminalOp should be terminal operation. // * @param mapper // * @return // */ // @TerminalOp // @Beta // public R transform(final Function, U> terminalOp, final Function mapper) { // return mapper.apply(terminalOp.apply(this)); // } // // /** // * // * @param // * @param terminalOp should be terminal operation. // * @param action // * @return // */ // @TerminalOp // @Beta // public R transform(final Function, R> terminalOp, final Consumer action) { // final R result = terminalOp.apply(this); // action.accept(result); // return result; // } /** * Checks if the current stream is parallel. * * @return {@code true} if the stream is parallel, {@code false} otherwise * @see Stream#isParallel() */ @Override public boolean isParallel() { return _stream.isParallel(); } /** * Returns an equivalent stream that is sequential. * * @return a sequential stream * @see Stream#sequential() */ @Override public EntryStream sequential() { return _stream.isParallel() ? of(_stream.sequential()) : this; } @Override protected EntryStream parallel(final int maxThreadNum, final int executorNumForVirtualThread, final Splitor splitor, final AsyncExecutor asyncExecutor, final boolean cancelUncompletedThreads) { return of(_stream.parallel(maxThreadNum, executorNumForVirtualThread, splitor, asyncExecutor, cancelUncompletedThreads)); } @Override protected int maxThreadNum() { return _stream.maxThreadNum(); } @Override protected Splitor splitor() { return _stream.splitor(); } @Override protected AsyncExecutor asyncExecutor() { return _stream.asyncExecutor(); } @Override protected boolean cancelUncompletedThreads() { return _stream.cancelUncompletedThreads(); } /** * Inverses the current EntryStream to a new EntryStream by DisposableEntry. * The elements can only be retrieved one by one, cannot be modified or saved. * The returned Stream does not support operations that require two or more elements at the same time * (e.g., sort, distinct, pairMap, slidingMap, sliding, split, toList, toSet, etc.). * * @return a new EntryStream with inverted keys and values as DisposableEntry * @throws IllegalStateException if the stream is parallel * @deprecated This method is deprecated and should not be used in parallel streams. * @see #inversed() */ @SequentialOnly @Deprecated @Beta public EntryStream inversedToDisposableEntry() { checkState(!_stream.isParallel(), "inversedER can't be applied to parallel stream"); final Function, DisposableEntry> mapper = new Function<>() { private final ReusableEntry entry = new ReusableEntry<>(); @Override public DisposableEntry apply(final Map.Entry e) { entry.set(e.getValue(), e.getKey()); return entry; } }; return map(mapper); } // /** // * Transforms the current EntryStream to a new EntryStream with disposable entries. // * The elements can only be retrieved one by one, cannot be modified or saved. // * The returned Stream does not support operations that require two or more elements at the same time // * (e.g., sort, distinct, pairMap, slidingMap, sliding, split, toList, toSet, etc.). // * // * @param the type of the keys in the resulting EntryStream // * @param the type of the values in the resulting EntryStream // * @param keyMapper the function to transform the keys // * @param valueMapper the function to transform the values // * @return a new EntryStream with the transformed keys and values as DisposableEntry // * @throws IllegalStateException if the stream is parallel // * @deprecated This method is deprecated and should not be used in parallel streams. // * @see #map(Function) // */ // @SequentialOnly // @Deprecated // @Beta // public EntryStream mapToDisposableEntry(final Function, ? extends KK> keyMapper, // final Function, ? extends VV> valueMapper) { // checkState(!_stream.isParallel(), "mapER can't be applied to parallel stream"); // // final Function, Map.Entry> mapper = new Function<>() { // private final ReusableEntry entry = new ReusableEntry<>(); // // @Override // public Map.Entry apply(final Map.Entry t) { // entry.set(keyMapper.apply(t), valueMapper.apply(t)); // // return entry; // } // }; // // return map(mapper); // } // // /** // * Transforms the current EntryStream to a new EntryStream with disposable entries. // * The elements can only be retrieved one by one, cannot be modified or saved. // * The returned Stream does not support operations that require two or more elements at the same time // * (e.g., sort, distinct, pairMap, slidingMap, sliding, split, toList, toSet, etc.). // * // * @param the type of the keys in the resulting EntryStream // * @param the type of the values in the resulting EntryStream // * @param keyMapper the function to transform the keys // * @param valueMapper the function to transform the values // * @return a new EntryStream with the transformed keys and values as DisposableEntry // * @throws IllegalStateException if the stream is parallel // * @deprecated This method is deprecated and should not be used in parallel streams. // * @see #map(BiFunction) // */ // @SequentialOnly // @Deprecated // @Beta // public EntryStream mapToDisposableEntry(final BiFunction keyMapper, // final BiFunction valueMapper) { // checkState(!_stream.isParallel(), "mapER can't be applied to parallel stream"); // // final Function, Map.Entry> mapper = new Function<>() { // private final ReusableEntry entry = new ReusableEntry<>(); // // @Override // public Map.Entry apply(final Map.Entry t) { // entry.set(keyMapper.apply(t.getKey(), t.getValue()), valueMapper.apply(t.getKey(), t.getValue())); // // return entry; // } // }; // // return map(mapper); // } // // /** // * Transforms the current EntryStream to a new EntryStream with disposable entries for keys. // * The elements can only be retrieved one by one, cannot be modified or saved. // * The returned Stream does not support operations that require two or more elements at the same time // * (e.g., sort, distinct, pairMap, slidingMap, sliding, split, toList, toSet, etc.). // * // * @param the type of the keys in the resulting EntryStream // * @param keyMapper the function to transform the keys // * @return a new EntryStream with the transformed keys as DisposableEntry // * @throws IllegalStateException if the stream is parallel // * @deprecated This method is deprecated and should not be used in parallel streams. // * @see #flatmapKey(Function) // */ // @SequentialOnly // @Deprecated // @Beta // public EntryStream flatMapKeyToDisposableEntry(final Function> keyMapper) { // checkState(!_stream.isParallel(), "flatMapKeyER can't be applied to parallel stream"); // // final Function, Stream>> mapper2 = e -> keyMapper.apply(e.getKey()).map(new Function>() { // private final ReusableEntry entry = new ReusableEntry<>(); // // @Override // public Map.Entry apply(final KK kk) { // entry.set(kk, e.getValue()); // return entry; // } // }); // // return flattMap(mapper2); // } // // /** // * Transforms the current EntryStream to a new EntryStream with disposable entries for keys. // * The elements can only be retrieved one by one, cannot be modified or saved. // * The returned Stream does not support operations that require two or more elements at the same time // * (e.g., sort, distinct, pairMap, slidingMap, sliding, split, toList, toSet, etc.). // * // * @param the type of the keys in the resulting EntryStream // * @param keyMapper the function to transform the keys // * @return a new EntryStream with the transformed keys as DisposableEntry // * @throws IllegalStateException if the stream is parallel // * @deprecated This method is deprecated and should not be used in parallel streams. // * @see #flatmapKey(Function) // */ // @SequentialOnly // @Deprecated // @Beta // public EntryStream flatmapKeyToDisposableEntry(final Function> keyMapper) { //NOSONAR // checkState(!_stream.isParallel(), "flatMapKeyER can't be applied to parallel stream"); // // final Function, Stream>> mapper2 = e -> Stream.of(keyMapper.apply(e.getKey())) // .map(new Function>() { // private final ReusableEntry entry = new ReusableEntry<>(); // // @Override // public Map.Entry apply(final KK kk) { // entry.set(kk, e.getValue()); // return entry; // } // }); // // return flattMap(mapper2); // } // // /** // * Transforms the current EntryStream to a new EntryStream with disposable entries for values. // * The elements can only be retrieved one by one, cannot be modified or saved. // * The returned Stream does not support operations that require two or more elements at the same time // * (e.g., sort, distinct, pairMap, slidingMap, sliding, split, toList, toSet, etc.). // * // * @param the type of the values in the resulting EntryStream // * @param valueMapper the function to transform the values // * @return a new EntryStream with the transformed values as DisposableEntry // * @throws IllegalStateException if the stream is parallel // * @deprecated This method is deprecated and should not be used in parallel streams. // * @see #flatmapValue(Function) // */ // @SequentialOnly // @Deprecated // @Beta // public EntryStream flatMapValueToDisposableEntry(final Function> valueMapper) { // checkState(!_stream.isParallel(), "flatMapValueER can't be applied to parallel stream"); // // final Function, Stream>> mapper2 = e -> valueMapper.apply(e.getValue()).map(new Function>() { // private final ReusableEntry entry = new ReusableEntry<>(); // // @Override // public Map.Entry apply(final VV vv) { // entry.set(e.getKey(), vv); // return entry; // } // }); // // return flattMap(mapper2); // } // // /** // * Transforms the current EntryStream to a new EntryStream with disposable entries for values. // * The elements can only be retrieved one by one, cannot be modified or saved. // * The returned Stream does not support operations that require two or more elements at the same time // * (e.g., sort, distinct, pairMap, slidingMap, sliding, split, toList, toSet, etc.). // * // * @param the type of the values in the resulting EntryStream // * @param valueMapper the function to transform the values // * @return a new EntryStream with the transformed values as DisposableEntry // * @throws IllegalStateException if the stream is parallel // * @deprecated This method is deprecated and should not be used in parallel streams // * @see #flatmapValue(Function) // */ // @SequentialOnly // @Deprecated // @Beta // public EntryStream flatmapValueToDisposableEntry(final Function> valueMapper) { //NOSONAR // checkState(!_stream.isParallel(), "flatMapValueER can't be applied to parallel stream"); // // final Function, Stream>> mapper2 = e -> Stream.of(valueMapper.apply(e.getValue())) // .map(new Function>() { // private final ReusableEntry entry = new ReusableEntry<>(); // // @Override // public Map.Entry apply(final VV vv) { // entry.set(e.getKey(), vv); // return entry; // } // }); // // return flattMap(mapper2); // } /** * Applies the provided function to this EntryStream if it is not empty. * * @param the type of the result * @param the type of the exception that can be thrown when processing elements in the EntryStream * @param func a non-interfering, stateless function to apply to each element if this EntryStream is not empty * @return an Optional describing the result of applying a function to the elements of this EntryStream if it is not empty, or an empty Optional if the EntryStream is empty * @throws E if any element processing results in an exception * @see Stream#applyIfNotEmpty(Throwables.Function) */ @Override public Optional applyIfNotEmpty(final Throwables.Function, ? extends R, E> func) throws E { final EntryStream tmp = this; final Throwables.Function>, ? extends R, E> func2 = t -> func.apply(tmp); return _stream.applyIfNotEmpty(func2); } /** * Applies the provided consumer to this EntryStream if it is not empty. * * @param the type of the exception that can be thrown when processing elements in the EntryStream * @param action a non-interfering, stateless action to perform if this EntryStream is not empty * @return an OrElse instance which can be used to chain further action if the EntryStream is empty * @throws E if any element processing results in an exception * @see Stream#acceptIfNotEmpty(Throwables.Consumer) */ @Override public OrElse acceptIfNotEmpty(final Throwables.Consumer, E> action) throws E { final EntryStream tmp = this; final Throwables.Consumer>, E> action2 = t -> action.accept(tmp); return _stream.acceptIfNotEmpty(action2); } /** * Registers a close handler to be invoked when the stream is closed. * This method can be called multiple times to register multiple handlers. * Handlers are invoked in the order they were added, first-added, first-invoked. * * @param closeHandler A Runnable whose run method will be invoked when the stream is closed. * @return A new EntryStream instance with the close handler registered. */ @Override public EntryStream onClose(final Runnable closeHandler) { return of(_stream.onClose(closeHandler)); } /** * Closes the EntryStream. */ @Override public synchronized void close() { _stream.close(); } @SuppressWarnings({ "rawtypes" }) static Function, Stream>> mapFunc() { return (Function) mapper_func; } // @SuppressWarnings("rawtypes") // private static final EntryStream EMPTY_STREAM = new EntryStream(Stream. empty()); /** * Returns an empty EntryStream. * * @param the type of keys in the EntryStream * @param the type of values in the EntryStream * @return an empty EntryStream * @see Stream#empty() */ public static EntryStream empty() { return new EntryStream<>(Stream.> empty()); } /** * Returns an EntryStream that is lazily populated by the provided supplier. *
* @implNote * This is equal to: {@code Stream.just(supplier).flattMapToEntry(Supplier::get)}. * * @param the type of keys in the EntryStream * @param the type of values in the EntryStream * @param supplier the supplier that provides the EntryStream * @return an EntryStream that is lazily populated by the provided supplier * @see Stream#defer(Supplier) */ public static EntryStream defer(final Supplier> supplier) { // NOSONAR N.checkArgNotNull(supplier, cs.supplier); //noinspection resource return Stream.just(supplier).flattMapToEntry(Supplier::get); } /** * Returns an EntryStream containing the provided entry if it is not {@code null}, otherwise returns an empty EntryStream. * * @param the type of keys in the EntryStream * @param the type of values in the EntryStream * @param entry the Map.Entry to be included in the EntryStream if it is not null * @return an EntryStream containing the provided entry if it is not {@code null}, otherwise an empty EntryStream * @see Stream#ofNullable(Object) */ public static EntryStream ofNullable(final Map.Entry entry) { if (entry == null) { return EntryStream.empty(); } return of(Stream.of(entry)); } /** * Returns an EntryStream containing a single entry with the provided key and value. * * @param the type of keys in the EntryStream * @param the type of values in the EntryStream * @param k1 the key to be included in the EntryStream * @param v1 the value to be included in the EntryStream * @return an EntryStream containing a single entry with the provided key and value * @see Stream#of(Object[]) */ public static EntryStream of(final K k1, final V v1) { return of(Stream.of(new SimpleImmutableEntry<>(k1, v1))); } /** * Returns an EntryStream containing two entries with the provided keys and values. * * @param the type of keys in the EntryStream * @param the type of values in the EntryStream * @param k1 the key of the first entry * @param v1 the value of the first entry * @param k2 the key of the second entry * @param v2 the value of the second entry * @return an EntryStream containing two entries with the provided keys and values * @see Stream#of(Object[]) */ public static EntryStream of(final K k1, final V v1, final K k2, final V v2) { return of(Stream.of(new SimpleImmutableEntry<>(k1, v1), new SimpleImmutableEntry<>(k2, v2))); } /** * Returns an EntryStream containing three entries with the provided keys and values. * * @param the type of keys in the EntryStream * @param the type of values in the EntryStream * @param k1 the key of the first entry * @param v1 the value of the first entry * @param k2 the key of the second entry * @param v2 the value of the second entry * @param k3 the key of the third entry * @param v3 the value of the third entry * @return an EntryStream containing three entries with the provided keys and values * @see Stream#of(Object[]) */ public static EntryStream of(final K k1, final V v1, final K k2, final V v2, final K k3, final V v3) { return of(Stream.of(new SimpleImmutableEntry<>(k1, v1), new SimpleImmutableEntry<>(k2, v2), new SimpleImmutableEntry<>(k3, v3))); } /** * Returns an EntryStream containing four entries with the provided keys and values. * * @param the type of keys in the EntryStream * @param the type of values in the EntryStream * @param k1 the key of the first entry * @param v1 the value of the first entry * @param k2 the key of the second entry * @param v2 the value of the second entry * @param k3 the key of the third entry * @param v3 the value of the third entry * @param k4 the key of the fourth entry * @param v4 the value of the fourth entry * @return an EntryStream containing four entries with the provided keys and values * @see Stream#of(Object[]) */ public static EntryStream of(final K k1, final V v1, final K k2, final V v2, final K k3, final V v3, final K k4, final V v4) { return of(Stream.of(new SimpleImmutableEntry<>(k1, v1), new SimpleImmutableEntry<>(k2, v2), new SimpleImmutableEntry<>(k3, v3), new SimpleImmutableEntry<>(k4, v4))); } /** * Returns an EntryStream containing five entries with the provided keys and values. * * @param the type of keys in the EntryStream * @param the type of values in the EntryStream * @param k1 the key of the first entry * @param v1 the value of the first entry * @param k2 the key of the second entry * @param v2 the value of the second entry * @param k3 the key of the third entry * @param v3 the value of the third entry * @param k4 the key of the fourth entry * @param v4 the value of the fourth entry * @param k5 the key of the fifth entry * @param v5 the value of the fifth entry * @return an EntryStream containing five entries with the provided keys and values * @see Stream#of(Object[]) */ public static EntryStream of(final K k1, final V v1, final K k2, final V v2, final K k3, final V v3, final K k4, final V v4, final K k5, final V v5) { return of(Stream.of(new SimpleImmutableEntry<>(k1, v1), new SimpleImmutableEntry<>(k2, v2), new SimpleImmutableEntry<>(k3, v3), new SimpleImmutableEntry<>(k4, v4), new SimpleImmutableEntry<>(k5, v5))); } /** * Returns an EntryStream containing six entries with the provided keys and values. * * @param the type of keys in the EntryStream * @param the type of values in the EntryStream * @param k1 the key of the first entry * @param v1 the value of the first entry * @param k2 the key of the second entry * @param v2 the value of the second entry * @param k3 the key of the third entry * @param v3 the value of the third entry * @param k4 the key of the fourth entry * @param v4 the value of the fourth entry * @param k5 the key of the fifth entry * @param v5 the value of the fifth entry * @param k6 the key of the sixth entry * @param v6 the value of the sixth entry * @return an EntryStream containing six entries with the provided keys and values * @see Stream#of(Object[]) */ public static EntryStream of(final K k1, final V v1, final K k2, final V v2, final K k3, final V v3, final K k4, final V v4, final K k5, final V v5, final K k6, final V v6) { return of(Stream.of(new SimpleImmutableEntry<>(k1, v1), new SimpleImmutableEntry<>(k2, v2), new SimpleImmutableEntry<>(k3, v3), new SimpleImmutableEntry<>(k4, v4), new SimpleImmutableEntry<>(k5, v5), new SimpleImmutableEntry<>(k6, v6))); } /** * Returns an EntryStream containing seven entries with the provided keys and values. * * @param the type of keys in the EntryStream * @param the type of values in the EntryStream * @param k1 the key of the first entry * @param v1 the value of the first entry * @param k2 the key of the second entry * @param v2 the value of the second entry * @param k3 the key of the third entry * @param v3 the value of the third entry * @param k4 the key of the fourth entry * @param v4 the value of the fourth entry * @param k5 the key of the fifth entry * @param v5 the value of the fifth entry * @param k6 the key of the sixth entry * @param v6 the value of the sixth entry * @param k7 the key of the seventh entry * @param v7 the value of the seventh entry * @return an EntryStream containing seven entries with the provided keys and values * @see Stream#of(Object[]) */ public static EntryStream of(final K k1, final V v1, final K k2, final V v2, final K k3, final V v3, final K k4, final V v4, final K k5, final V v5, final K k6, final V v6, final K k7, final V v7) { return of(Stream.of(new SimpleImmutableEntry<>(k1, v1), new SimpleImmutableEntry<>(k2, v2), new SimpleImmutableEntry<>(k3, v3), new SimpleImmutableEntry<>(k4, v4), new SimpleImmutableEntry<>(k5, v5), new SimpleImmutableEntry<>(k6, v6), new SimpleImmutableEntry<>(k7, v7))); } static EntryStream of(final Stream> s) { return new EntryStream<>(s); } /** * Returns an EntryStream containing the entries from the given map. * * @param the type of keys in the EntryStream * @param the type of values in the EntryStream * @param map the entries to be included in the EntryStream * @return an EntryStream containing the entries from the given map * @see Stream#of(Object[]) */ public static EntryStream of(final Map map) { return new EntryStream<>(map, Stream.of(map)); } /** * Returns an EntryStream containing the entries from the given iterator. * * @param the type of keys in the EntryStream * @param the type of values in the EntryStream * @param iterator the iterator providing the entries to be included in the EntryStream * @return an EntryStream containing the entries from the given iterator */ public static EntryStream of(final Iterator> iterator) { return new EntryStream<>(Stream.of(iterator)); } /** * Returns an EntryStream containing the entries from the given iterable. * * @param the type of keys in the EntryStream * @param the type of values in the EntryStream * @param entries the iterable providing the entries to be included in the EntryStream * @return an EntryStream containing the entries from the given iterable */ public static EntryStream of(final Iterable> entries) { return new EntryStream<>(Stream.of(entries)); } // @SafeVarargs // public static EntryStream of(final Map.Entry... entries) { // return new EntryStream(Stream.of(entries)); // } /** * Returns an EntryStream containing the entries from the given Multimap. * * @param the type of keys in the EntryStream * @param the type of values in the EntryStream * @param mulitmap the iterable providing the entries to be included in the EntryStream * @return an EntryStream containing the entries from the given Multimap */ public static > EntryStream of(final Multimap mulitmap) { return mulitmap == null ? EntryStream.empty() : (EntryStream) mulitmap.entryStream(); } /** * Creates an EntryStream from the provided array and key mapper function. * * @param the type of elements in the array * @param the type of keys in the EntryStream * @param a the array to be converted into an EntryStream * @param keyMapper the function to map array elements to keys * @return an EntryStream containing the entries from the provided array */ public static EntryStream of(final T[] a, final Function keyMapper) { final Function valueMapper = Fn.identity(); //noinspection resource return Stream.of(a).mapToEntry(keyMapper, valueMapper); } /** * Creates an EntryStream from the provided array and key and value mapper functions. * * @param the type of elements in the array * @param the type of keys in the EntryStream * @param the type of values in the EntryStream * @param a the array to be converted into an EntryStream * @param keyMapper the function to map array elements to keys * @param valueMapper the function to map array elements to values * @return an EntryStream containing the entries from the provided array */ public static EntryStream of(final T[] a, final Function keyMapper, final Function valueMapper) { //noinspection resource return Stream.of(a).mapToEntry(keyMapper, valueMapper); } /** * Creates an EntryStream from the provided collection and key mapper function. * * @param the type of elements in the collection * @param the type of keys in the EntryStream * @param c the collection to be converted into an EntryStream * @param keyMapper the function to map collection elements to keys * @return an EntryStream containing the entries from the provided collection */ public static EntryStream of(final Iterable c, final Function keyMapper) { final Function valueMapper = Fn.identity(); //noinspection resource return Stream.of(c).mapToEntry(keyMapper, valueMapper); } /** * Creates an EntryStream from the provided collection and key and value mapper functions. * * @param the type of elements in the collection * @param the type of keys in the EntryStream * @param the type of values in the EntryStream * @param c the collection to be converted into an EntryStream * @param keyMapper the function to map collection elements to keys * @param valueMapper the function to map collection elements to values * @return an EntryStream containing the entries from the provided collection */ public static EntryStream of(final Iterable c, final Function keyMapper, final Function valueMapper) { //noinspection resource return Stream.of(c).mapToEntry(keyMapper, valueMapper); } /** * Creates an EntryStream from the provided iterator and key mapper function. * * @param the type of elements in the iterator * @param the type of keys in the EntryStream * @param iter the iterator to be converted into an EntryStream * @param keyMapper the function to map iterator elements to keys * @return an EntryStream containing the entries from the provided iterator */ public static EntryStream of(final Iterator iter, final Function keyMapper) { final Function valueMapper = Fn.identity(); //noinspection resource return Stream.of(iter).mapToEntry(keyMapper, valueMapper); } /** * Creates an EntryStream from the provided iterator and key and value mapper functions. * * @param the type of elements in the iterator * @param the type of keys in the EntryStream * @param the type of values in the EntryStream * @param iter the iterator to be converted into an EntryStream * @param keyMapper the function to map iterator elements to keys * @param valueMapper the function to map iterator elements to values * @return an EntryStream containing the entries from the provided iterator */ public static EntryStream of(final Iterator iter, final Function keyMapper, final Function valueMapper) throws IllegalArgumentException { //noinspection resource return Stream.of(iter).mapToEntry(keyMapper, valueMapper); } /** * Concatenates multiple maps into a single EntryStream. * * @param the type of keys in the maps * @param the type of values in the maps * @param maps the maps to be concatenated * @return an EntryStream containing all entries from the provided maps * @see Stream#concat(Iterable[]) */ @SafeVarargs public static EntryStream concat(final Map... maps) { if (N.isEmpty(maps)) { return EntryStream.empty(); } //noinspection resource return Stream.of(maps).flatmapToEntry(Fn.identity()); } /** * Concatenates multiple maps into a single EntryStream. * * @param the type of keys in the maps * @param the type of values in the maps * @param maps the maps to be concatenated * @return an EntryStream containing all entries from the provided maps * @see Stream#concat(Iterable[]) */ public static EntryStream concat(final Collection> maps) { if (N.isEmpty(maps)) { return EntryStream.empty(); } //noinspection resource return Stream.of(maps).flatmapToEntry(Fn.> identity()); } /** * Merges two maps into a single EntryStream based on the provided nextSelector function. * The nextSelector function determines which entry from the two maps should be selected next. * * @param the type of keys in the maps * @param the type of values in the maps * @param a the first map to be merged * @param b the second map to be merged * @param nextSelector a function that determines the next entry to be selected from the two maps * @return an EntryStream containing the merged entries from the two maps * @see N#merge(Iterable, Iterable, BiFunction) */ public static EntryStream merge(final Map a, final Map b, final BiFunction, ? super Map.Entry, MergeResult> nextSelector) throws IllegalArgumentException { N.checkArgNotNull(nextSelector); if (N.isEmpty(a)) { return of(b); } else if (N.isEmpty(b)) { return of(a); } else { //noinspection resource return Stream.merge(a.entrySet(), b.entrySet(), nextSelector).mapToEntry(Fn.identity()); } } /** * Merges three maps into a single EntryStream based on the provided nextSelector function. * The nextSelector function determines which entry from the three maps should be selected next. * * @param the type of keys in the maps * @param the type of values in the maps * @param a the first map to be merged * @param b the second map to be merged * @param c the third map to be merged * @param nextSelector a function that determines the next entry to be selected from the three maps * @return an EntryStream containing the merged entries from the three maps * @see N#merge(Iterable, Iterable, BiFunction) */ public static EntryStream merge(final Map a, final Map b, final Map c, final BiFunction, ? super Map.Entry, MergeResult> nextSelector) throws IllegalArgumentException { N.checkArgNotNull(nextSelector); if (N.isEmpty(a)) { return merge(b, c, nextSelector); } else if (N.isEmpty(b)) { return merge(a, c, nextSelector); } else if (N.isEmpty(c)) { return merge(a, b, nextSelector); } else { //noinspection resource return Stream.merge(a.entrySet(), b.entrySet(), c.entrySet(), nextSelector).mapToEntry(Fn.identity()); } } /** * Merges a collection of maps into a single stream based on the provided nextSelector function. * The nextSelector function determines which entry from the maps should be selected next. * * @param the type of keys in the maps * @param the type of values in the maps * @param maps the collection of maps to be merged * @param nextSelector a function that determines the next entry to be selected from the maps * @return a stream containing the merged entries from the collection of maps */ public static EntryStream merge(final Collection> maps, final BiFunction, ? super Map.Entry, MergeResult> nextSelector) throws IllegalArgumentException { N.checkArgNotNull(nextSelector); if (N.isEmpty(maps)) { return EntryStream.empty(); } final List>> entryIteratorList = new ArrayList<>(maps.size()); for (final Map map : maps) { if (N.notEmpty(map)) { entryIteratorList.add(map.entrySet()); } } //noinspection resource return Stream.mergeIterables(entryIteratorList, nextSelector).mapToEntry(Fn.identity()); } /** * Zips the arrays of keys/values into a single EntryStream until one of them runs out of values. * * @param the type of keys * @param the type of values * @param keys the array of keys * @param values the array of values * @return an EntryStream containing entries created from the provided keys and values * @see Stream#zip(Object[], Object[], BiFunction) * @see N#zip(Object[], Object[], BiFunction) */ public static EntryStream zip(final K[] keys, final V[] values) { if (N.isEmpty(keys) || N.isEmpty(values)) { return EntryStream.empty(); } final BiFunction> zipFunction = Fn.entry(); final Function, Map.Entry> mapper = Fn.identity(); //noinspection resource return Stream.zip(keys, values, zipFunction).mapToEntry(mapper); } /** * Zips the arrays of keys/values into a single EntryStream until all of them runs out of values. * If one array is shorter, the provided default values are used for the remaining elements. * * @param the type of keys * @param the type of values * @param keys the array of keys * @param values the array of values * @param valueForNoneKey the default value to use if the key array is shorter * @param valueForNoneValue the default value to use if the value array is shorter * @return an EntryStream containing entries created from the provided keys and values * @see Stream#zip(Object[], Object[], Object, Object, BiFunction) * @see N#zip(Object[], Object[], Object, Object, BiFunction) */ public static EntryStream zip(final K[] keys, final V[] values, final K valueForNoneKey, final V valueForNoneValue) { if (N.isEmpty(keys) && N.isEmpty(values)) { return EntryStream.empty(); } final BiFunction> zipFunction = Fn.entry(); final Function, Map.Entry> mapper = Fn.identity(); //noinspection resource return Stream.zip(keys, values, valueForNoneKey, valueForNoneValue, zipFunction).mapToEntry(mapper); } /** * Zips two iterables into an EntryStream until one of them runs out of values. * * @param the type of keys * @param the type of values * @param keys the iterable of keys * @param values the iterable of values * @return an EntryStream containing entries created from the provided keys and values * @see Stream#zip(Iterable, Iterable, BiFunction) * @see N#zip(Iterable, Iterable, BiFunction) */ public static EntryStream zip(final Iterable keys, final Iterable values) { if (keys == null || values == null) { return EntryStream.empty(); } final BiFunction> zipFunction = Fn.entry(); final Function, Map.Entry> mapper = Fn.identity(); //noinspection resource return Stream.zip(keys, values, zipFunction).mapToEntry(mapper); } /** * Zips two iterables into an EntryStream until all of them runs out of values. * If one iterable is shorter, the provided default values are used for the remaining elements. * * @param the type of keys * @param the type of values * @param keys the iterable of keys * @param values the iterable of values * @param valueForNoneKey the default value to use if the key iterable is shorter * @param valueForNoneValue the default value to use if the value iterable is shorter * @return an EntryStream containing entries created from the provided keys and values * @see Stream#zip(Iterable, Iterable, Object, Object, BiFunction) * @see N#zip(Iterable, Iterable, Object, Object, BiFunction) */ public static EntryStream zip(final Iterable keys, final Iterable values, final K valueForNoneKey, final V valueForNoneValue) { if (keys == null && values == null) { return EntryStream.empty(); } final BiFunction> zipFunction = Fn.entry(); final Function, Map.Entry> mapper = Fn.identity(); //noinspection resource return Stream.zip(keys, values, valueForNoneKey, valueForNoneValue, zipFunction).mapToEntry(mapper); } /** * Zips two iterators into an EntryStream until one of them runs out of values. * * @param the type of keys * @param the type of values * @param keys the iterator of keys * @param values the iterator of values * @return an EntryStream containing entries created from the provided keys and values * @see Stream#zip(Iterator, Iterator, BiFunction) */ public static EntryStream zip(final Iterator keys, final Iterator values) { if (keys == null || values == null) { return EntryStream.empty(); } final BiFunction> zipFunction = Fn.entry(); final Function, Map.Entry> mapper = Fn.identity(); //noinspection resource return Stream.zip(keys, values, zipFunction).mapToEntry(mapper); } /** * Zips two iterators into an EntryStream until all of them runs out of values. * If one iterator is shorter, the provided default values are used for the remaining elements. * * @param the type of keys * @param the type of values * @param keys the iterator of keys * @param values the iterator of values * @param valueForNoneKey the default value to use if the key iterator is shorter * @param valueForNoneValue the default value to use if the value iterator is shorter * @return an EntryStream containing entries created from the provided keys and values * @see Stream#zip(Iterator, Iterator, Object, Object, BiFunction) */ public static EntryStream zip(final Iterator keys, final Iterator values, final K valueForNoneKey, final V valueForNoneValue) { if (keys == null && values == null) { return EntryStream.empty(); } final BiFunction> zipFunction = Fn.entry(); final Function, Map.Entry> mapper = Fn.identity(); //noinspection resource return Stream.zip(keys, values, valueForNoneKey, valueForNoneValue, zipFunction).mapToEntry(mapper); } static class ReusableEntry extends DisposableEntry { private K key = null; private V value = null; private boolean flag = false; //check if it's used/read. @Override public K getKey() { flag = false; return key; } @Override public V getValue() { flag = false; return value; } // @Override // public V setValue(V value) { // throw new UnsupportedOperationException(); // } public void set(final K key, final V value) { if (flag) { throw new IllegalStateException(); } this.key = key; this.value = value; flag = true; } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (obj instanceof ReusableEntry) { final ReusableEntry other = (ReusableEntry) obj; return N.equals(key, other.key) && N.equals(value, other.value); } return false; } @Override public int hashCode() { return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode()); } @Override public String toString() { flag = false; return key + "=" + value; } } }