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

com.landawn.abacus.util.Seq Maven / Gradle / Ivy

There is a newer version: 1.10.1
Show newest version
/*
 * Copyright (c) 2017, 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
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.landawn.abacus.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;

import com.landawn.abacus.annotation.Beta;
import com.landawn.abacus.exception.DuplicatedResultException;
import com.landawn.abacus.util.Fn.BiFunctions;
import com.landawn.abacus.util.Fn.FN;
import com.landawn.abacus.util.Fn.Factory;
import com.landawn.abacus.util.Fn.Suppliers;
import com.landawn.abacus.util.u.Nullable;
import com.landawn.abacus.util.u.Optional;
import com.landawn.abacus.util.u.OptionalDouble;
import com.landawn.abacus.util.u.OptionalInt;
import com.landawn.abacus.util.function.BiConsumer;
import com.landawn.abacus.util.function.BiFunction;
import com.landawn.abacus.util.function.Function;
import com.landawn.abacus.util.function.IntFunction;
import com.landawn.abacus.util.function.Supplier;
import com.landawn.abacus.util.stream.Collector;

/**
 * It's an read-only wrapper for Collection to support more daily used/functional methods.
 * All the operations are null safety. And an empty String/Array/Collection/Optional/Nullable will be returned if possible, instead of null.
 * 
 * 
* Seq should not be passed as a parameter or returned as a result because it's a pure utility class for the operations/calculation based on Collection/Array * * @since 0.8 * * @author Haiyang Li */ @Beta public final class Seq extends ImmutableCollection { @SuppressWarnings("rawtypes") private static final Seq EMPTY = new Seq<>(Collections.EMPTY_LIST); /** * The returned Seq and the specified Collection are backed by the same data. * Any changes to one will appear in the other. * * @param c */ Seq(final Collection c) { super(c == null ? Collections.EMPTY_LIST : c); } public static Seq empty() { return EMPTY; } public static Seq just(T t) { return of(t); } @SafeVarargs public static Seq of(final T... a) { if (N.isNullOrEmpty(a)) { return EMPTY; } return of(Arrays.asList(a)); } /** * The returned Seq and the specified Collection are backed by the same data. * Any changes to one will appear in the other. * * @param c * @return */ public static Seq of(Collection c) { if (N.isNullOrEmpty(c)) { return EMPTY; } return new Seq<>(c); } /** * * @param map * @return */ public static Seq> of(Map map) { if (N.isNullOrEmpty(map)) { return EMPTY; } return of(map.entrySet()); } // /** // * Returns the Collection the Seq is backed with recursively. // * // * @return // */ // public Collection interior() { // if (coll == null) { // return coll; // } // // Collection tmp = coll; // // if (tmp instanceof Seq) { // while (tmp instanceof Seq) { // tmp = ((Seq) tmp).coll; // } // } // // if (tmp instanceof SubCollection) { // while (tmp instanceof SubCollection) { // tmp = ((SubCollection) tmp).c; // } // } // // if (tmp instanceof Seq) { // return ((Seq) tmp).interior(); // } else { // return tmp; // } // } @Override public boolean contains(Object e) { if (N.isNullOrEmpty(coll)) { return false; } return coll.contains(e); } @Override public boolean containsAll(Collection c) { if (N.isNullOrEmpty(c)) { return true; } else if (N.isNullOrEmpty(coll)) { return false; } return coll.containsAll(c); } public boolean containsAll(Object[] a) { if (N.isNullOrEmpty(a)) { return true; } else if (N.isNullOrEmpty(coll)) { return false; } return containsAll(Arrays.asList(a)); } public boolean containsAny(Collection c) { if (N.isNullOrEmpty(coll) || N.isNullOrEmpty(c)) { return false; } return !disjoint(c); } public boolean containsAny(Object[] a) { if (N.isNullOrEmpty(coll) || N.isNullOrEmpty(a)) { return false; } return !disjoint(a); } public boolean disjoint(final Collection c) { return N.disjoint(this.coll, c); } public boolean disjoint(final Object[] a) { if (N.isNullOrEmpty(coll) || N.isNullOrEmpty(a)) { return true; } return disjoint(Arrays.asList(a)); } /** * * @param b * @return * @see IntList#intersection(IntList) */ public List intersection(Collection b) { return N.intersection(coll, b); } public List intersection(final Object[] a) { return N.intersection(coll, Array.asList(a)); } /** * * @param b * @return * @see IntList#difference(IntList) */ public List difference(Collection b) { return N.difference(coll, b); } public List difference(final Object[] a) { return N.difference(coll, Array.asList(a)); } /** * * @param b * @return this.difference(b).addAll(b.difference(this)) * @see IntList#symmetricDifference(IntList) */ public List symmetricDifference(Collection b) { return N.symmetricDifference(coll, b); } public List symmetricDifference(final T[] a) { return N.symmetricDifference(coll, Array.asList(a)); } public int occurrencesOf(final Object objectToFind) { return N.isNullOrEmpty(coll) ? 0 : N.occurrencesOf(coll, objectToFind); } @SuppressWarnings("rawtypes") public Nullable min() { return size() == 0 ? (Nullable) Nullable.empty() : Nullable.of((T) N.min((Collection) coll)); } public Nullable min(Comparator cmp) { return size() == 0 ? (Nullable) Nullable.empty() : Nullable.of(N.min(coll, cmp)); } @SuppressWarnings("rawtypes") public Nullable minBy(final Function keyMapper) { return min(Fn.comparingBy(keyMapper)); } @SuppressWarnings("rawtypes") public Nullable max() { return size() == 0 ? (Nullable) Nullable.empty() : Nullable.of((T) N.max((Collection) coll)); } public Nullable max(Comparator cmp) { return size() == 0 ? (Nullable) Nullable.empty() : Nullable.of(N.max(coll, cmp)); } @SuppressWarnings("rawtypes") public Nullable maxBy(final Function keyMapper) { return max(Fn.comparingBy(keyMapper)); } @SuppressWarnings("rawtypes") public Nullable median() { return size() == 0 ? (Nullable) Nullable.empty() : Nullable.of((T) N.median((Collection) coll)); } public Nullable median(Comparator cmp) { return size() == 0 ? (Nullable) Nullable.empty() : Nullable.of(N.median(coll, cmp)); } @SuppressWarnings("rawtypes") public Nullable kthLargest(final int k) { N.checkArgPositive(k, "k"); return size() < k ? (Nullable) Nullable.empty() : Nullable.of((T) N.kthLargest((Collection) coll, k)); } public Nullable kthLargest(final int k, Comparator cmp) { N.checkArgPositive(k, "k"); return size() < k ? (Nullable) Nullable.empty() : Nullable.of(N.kthLargest(coll, k, cmp)); } public int sumInt(final Try.ToIntFunction mapper) throws E { if (N.isNullOrEmpty(coll)) { return 0; } return N.sumInt(coll, mapper); } public long sumLong(final Try.ToLongFunction mapper) throws E { if (N.isNullOrEmpty(coll)) { return 0L; } return N.sumLong(coll, mapper); } public double sumDouble(final Try.ToDoubleFunction mapper) throws E { if (N.isNullOrEmpty(coll)) { return 0L; } return N.sumDouble(coll, mapper); } public OptionalDouble averageInt(final Try.ToIntFunction mapper) throws E { return N.averageInt(coll, mapper); } public OptionalDouble averageLong(final Try.ToLongFunction mapper) throws E { return N.averageLong(coll, mapper); } public OptionalDouble averageDouble(final Try.ToDoubleFunction mapper) throws E { return N.averageDouble(coll, mapper); } public void foreach(final Try.Consumer action) throws E { N.forEach(coll, action); } public void forEach(final Try.Consumer action, Try.Runnable onComplete) throws E, E2 { N.forEach(coll, action); onComplete.run(); } // public void forEach(int fromIndex, final int toIndex, final Consumer action) throws E { // N.forEach(coll, fromIndex, toIndex, action); // } public void forEach(final Try.IndexedConsumer action) throws E { N.forEach(coll, action); } public void forEach(final Try.Function, E> flatMapper, final Try.BiConsumer action) throws E, E2 { N.forEach(coll, flatMapper, action); } public void forEach( final Try.Function, E> flatMapper, final Try.Function, E2> flatMapper2, final Try.TriConsumer action) throws E, E2, E3 { N.forEach(coll, flatMapper, flatMapper2, action); } public void forEachNonNull(final Try.Consumer action) throws E { N.forEachNonNull(coll, action); } public void forEachNonNull(final Try.Function, E> flatMapper, final Try.BiConsumer action) throws E, E2 { N.forEachNonNull(coll, flatMapper, action); } public void forEachNonNull( final Try.Function, E> flatMapper, final Try.Function, E2> flatMapper2, final Try.TriConsumer action) throws E, E2, E3 { N.forEachNonNull(coll, flatMapper, flatMapper2, action); } public void forEachPair(final Try.BiConsumer action) throws E { forEachPair(action, 1); } public void forEachPair(final Try.BiConsumer action, final int increment) throws E { N.checkArgNotNull(action); final int windowSize = 2; N.checkArgument(windowSize > 0 && increment > 0, "windowSize=%s and increment=%s must be bigger than 0", windowSize, increment); if (N.isNullOrEmpty(coll)) { return; } final Iterator iter = coll.iterator(); Iterators.forEachPair(iter, action, increment); } public void forEachTriple(final Try.TriConsumer action) throws E { forEachTriple(action, 1); } public void forEachTriple(final Try.TriConsumer action, final int increment) throws E { N.checkArgNotNull(action); final int windowSize = 3; N.checkArgument(windowSize > 0 && increment > 0, "windowSize=%s and increment=%s must be bigger than 0", windowSize, increment); if (N.isNullOrEmpty(coll)) { return; } final Iterator iter = coll.iterator(); Iterators.forEachTriple(iter, action, increment); } public Nullable first() { return N.first(coll); } public Optional firstNonNull() { return N.firstNonNull(coll); } /** * Return at most first n elements. * * @param n * @return */ public List first(final int n) { N.checkArgument(n >= 0, "'n' can't be negative: " + n); if (N.isNullOrEmpty(coll) || n == 0) { return new ArrayList<>(); } else if (coll.size() <= n) { return new ArrayList<>(coll); } else if (coll instanceof List) { return new ArrayList<>(((List) coll).subList(0, n)); } else { final List result = new ArrayList<>(N.min(n, coll.size())); int cnt = 0; for (T e : coll) { result.add(e); if (++cnt == n) { break; } } return result; } } public Nullable last() { return N.last(coll); } public Optional lastNonNull() { return N.lastNonNull(coll); } /** * Return at most last n elements. * * @param n * @return */ public List last(final int n) { N.checkArgument(n >= 0, "'n' can't be negative: " + n); if (N.isNullOrEmpty(coll) || n == 0) { return new ArrayList<>(); } else if (coll.size() <= n) { return new ArrayList<>(coll); } else if (coll instanceof List) { return new ArrayList<>(((List) coll).subList(coll.size() - n, coll.size())); } else { final List result = new ArrayList<>(N.min(n, coll.size())); final Iterator iter = coll.iterator(); int offset = coll.size() - n; while (offset-- > 0) { iter.next(); } while (iter.hasNext()) { result.add(iter.next()); } return result; } } public Nullable findFirst(Try.Predicate predicate) throws E { return Iterables.findFirst(coll, predicate); } public Nullable findLast(Try.Predicate predicate) throws E { return Iterables.findLast(coll, predicate); } public OptionalInt findFirstIndex(Try.Predicate predicate) throws E { return Iterables.findFirstIndex(coll, predicate); } public OptionalInt findLastIndex(Try.Predicate predicate) throws E { return Iterables.findLastIndex(coll, predicate); } public Nullable findFirstOrLast(final Try.Predicate predicateForFirst, final Try.Predicate predicateForLast) throws E, E2 { if (N.isNullOrEmpty(coll)) { return Nullable. empty(); } final Nullable res = findFirst(predicateForFirst); return res.isPresent() ? res : findLast(predicateForLast); } public OptionalInt findFirstOrLastIndex(final Try.Predicate predicateForFirst, final Try.Predicate predicateForLast) throws E, E2 { if (N.isNullOrEmpty(coll)) { return OptionalInt.empty(); } final OptionalInt res = findFirstIndex(predicateForFirst); return res.isPresent() ? res : findLastIndex(predicateForLast); } public Pair, Nullable> findFirstAndLast(final Try.Predicate predicate) throws E { return findFirstAndLast(predicate, predicate); } public Pair, Nullable> findFirstAndLast(final Try.Predicate predicateForFirst, final Try.Predicate predicateForLast) throws E, E2 { if (N.isNullOrEmpty(coll)) { return Pair.of(Nullable. empty(), Nullable. empty()); } return Pair.of(findFirst(predicateForFirst), findLast(predicateForLast)); } public Pair findFirstAndLastIndex(final Try.Predicate predicate) throws E { return findFirstAndLastIndex(predicate, predicate); } public Pair findFirstAndLastIndex(final Try.Predicate predicateForFirst, final Try.Predicate predicateForLast) throws E, E2 { if (N.isNullOrEmpty(coll)) { return Pair.of(OptionalInt.empty(), OptionalInt.empty()); } return Pair.of(findFirstIndex(predicateForFirst), findLastIndex(predicateForLast)); } public boolean allMatch(Try.Predicate filter) throws E { if (N.isNullOrEmpty(coll)) { return true; } for (T e : coll) { if (filter.test(e) == false) { return false; } } return true; } public boolean anyMatch(Try.Predicate filter) throws E { if (N.isNullOrEmpty(coll)) { return false; } for (T e : coll) { if (filter.test(e)) { return true; } } return false; } public boolean noneMatch(Try.Predicate filter) throws E { if (N.isNullOrEmpty(coll)) { return true; } for (T e : coll) { if (filter.test(e)) { return false; } } return true; } public boolean nMatch(final int atLeast, final int atMost, final Try.Predicate filter) throws E { N.checkArgNotNegative(atLeast, "atLeast"); N.checkArgNotNegative(atMost, "atMost"); N.checkArgument(atLeast <= atMost, "'atLeast' must be <= 'atMost'"); long cnt = 0; for (T e : coll) { if (filter.test(e)) { if (++cnt > atMost) { return false; } } } return cnt >= atLeast && cnt <= atMost; } public boolean hasDuplicates() { return N.hasDuplicates(coll, false); } public int count(Try.Predicate filter) throws E { return N.count(coll, filter); } public List filter(Try.Predicate filter) throws E { return N.filter(coll, filter); } public List filter(Try.Predicate filter, final int max) throws E { return N.filter(coll, filter, max); } public , E extends Exception> C filter(Try.Predicate filter, IntFunction supplier) throws E { return N.filter(coll, filter, supplier); } public , E extends Exception> C filter(Try.Predicate filter, final int max, IntFunction supplier) throws E { return N.filter(coll, filter, max, supplier); } public List takeWhile(Try.Predicate filter) throws E { N.checkArgNotNull(filter); final List result = new ArrayList<>(N.min(9, size())); if (N.isNullOrEmpty(coll)) { return result; } for (T e : coll) { if (filter.test(e)) { result.add(e); } else { break; } } return result; } public List takeWhileInclusive(Try.Predicate filter) throws E { N.checkArgNotNull(filter); final List result = new ArrayList<>(N.min(9, size())); if (N.isNullOrEmpty(coll)) { return result; } for (T e : coll) { result.add(e); if (filter.test(e) == false) { break; } } return result; } public List dropWhile(Try.Predicate filter) throws E { N.checkArgNotNull(filter); final List result = new ArrayList<>(N.min(9, size())); if (N.isNullOrEmpty(coll)) { return result; } final Iterator iter = iterator(); T e = null; while (iter.hasNext()) { e = iter.next(); if (filter.test(e) == false) { result.add(e); break; } } while (iter.hasNext()) { result.add(iter.next()); } return result; } public List skipUntil(final Try.Predicate filter) throws E { N.checkArgNotNull(filter); final List result = new ArrayList<>(N.min(9, size())); if (N.isNullOrEmpty(coll)) { return result; } final Iterator iter = iterator(); T e = null; while (iter.hasNext()) { e = iter.next(); if (filter.test(e)) { result.add(e); break; } } while (iter.hasNext()) { result.add(iter.next()); } return result; } public List map(final Try.Function func) throws E { return N.map(coll, func); } public BooleanList mapToBoolean(final Try.ToBooleanFunction func) throws E { return N.mapToBoolean(coll, func); } public CharList mapToChar(final Try.ToCharFunction func) throws E { return N.mapToChar(coll, func); } public ByteList mapToByte(final Try.ToByteFunction func) throws E { return N.mapToByte(coll, func); } public ShortList mapToShort(final Try.ToShortFunction func) throws E { return N.mapToShort(coll, func); } public IntList mapToInt(final Try.ToIntFunction func) throws E { return N.mapToInt(coll, func); } public LongList mapToLong(final Try.ToLongFunction func) throws E { return N.mapToLong(coll, func); } public FloatList mapToFloat(final Try.ToFloatFunction func) throws E { return N.mapToFloat(coll, func); } public DoubleList mapToDouble(final Try.ToDoubleFunction func) throws E { return N.mapToDouble(coll, func); } public List flatMap(final Try.Function, E> func) throws E { N.checkArgNotNull(func); final List result = new ArrayList<>(size() > N.MAX_ARRAY_SIZE / 2 ? N.MAX_ARRAY_SIZE : size() * 2); if (N.isNullOrEmpty(coll)) { return result; } for (T e : coll) { result.addAll(func.apply(e)); } return result; } public List flattMap(final Try.Function func) throws E { N.checkArgNotNull(func); final List result = new ArrayList<>(size() > N.MAX_ARRAY_SIZE / 2 ? N.MAX_ARRAY_SIZE : size() * 2); if (N.isNullOrEmpty(coll)) { return result; } R[] a = null; for (T e : coll) { a = func.apply(e); if (N.notNullOrEmpty(a)) { if (a.length < 9) { for (R r : a) { result.add(r); } } else { result.addAll(Arrays.asList(a)); } } } return result; } public BooleanList flatMapToBoolean(final Try.Function, E> func) throws E { N.checkArgNotNull(func); final BooleanList result = new BooleanList(size() > N.MAX_ARRAY_SIZE / 2 ? N.MAX_ARRAY_SIZE : size() * 2); if (N.isNullOrEmpty(coll)) { return result; } for (T e : coll) { for (boolean b : func.apply(e)) { result.add(b); } } return result; } public BooleanList flattMapToBoolean(final Try.Function func) throws E { N.checkArgNotNull(func); final BooleanList result = new BooleanList(size() > N.MAX_ARRAY_SIZE / 2 ? N.MAX_ARRAY_SIZE : size() * 2); if (N.isNullOrEmpty(coll)) { return result; } for (T e : coll) { result.addAll(func.apply(e)); } return result; } public CharList flatMapToChar(final Try.Function, E> func) throws E { N.checkArgNotNull(func); final CharList result = new CharList(size() > N.MAX_ARRAY_SIZE / 2 ? N.MAX_ARRAY_SIZE : size() * 2); if (N.isNullOrEmpty(coll)) { return result; } for (T e : coll) { for (char b : func.apply(e)) { result.add(b); } } return result; } public CharList flattMapToChar(final Try.Function func) throws E { N.checkArgNotNull(func); final CharList result = new CharList(size() > N.MAX_ARRAY_SIZE / 2 ? N.MAX_ARRAY_SIZE : size() * 2); if (N.isNullOrEmpty(coll)) { return result; } for (T e : coll) { result.addAll(func.apply(e)); } return result; } public ByteList flatMapToByte(final Try.Function, E> func) throws E { N.checkArgNotNull(func); final ByteList result = new ByteList(size() > N.MAX_ARRAY_SIZE / 2 ? N.MAX_ARRAY_SIZE : size() * 2); if (N.isNullOrEmpty(coll)) { return result; } for (T e : coll) { for (byte b : func.apply(e)) { result.add(b); } } return result; } public ByteList flattMapToByte(final Try.Function func) throws E { N.checkArgNotNull(func); final ByteList result = new ByteList(size() > N.MAX_ARRAY_SIZE / 2 ? N.MAX_ARRAY_SIZE : size() * 2); if (N.isNullOrEmpty(coll)) { return result; } for (T e : coll) { result.addAll(func.apply(e)); } return result; } public ShortList flatMapToShort(final Try.Function, E> func) throws E { N.checkArgNotNull(func); final ShortList result = new ShortList(size() > N.MAX_ARRAY_SIZE / 2 ? N.MAX_ARRAY_SIZE : size() * 2); if (N.isNullOrEmpty(coll)) { return result; } for (T e : coll) { for (short b : func.apply(e)) { result.add(b); } } return result; } public ShortList flattMapToShort(final Try.Function func) throws E { N.checkArgNotNull(func); final ShortList result = new ShortList(size() > N.MAX_ARRAY_SIZE / 2 ? N.MAX_ARRAY_SIZE : size() * 2); if (N.isNullOrEmpty(coll)) { return result; } for (T e : coll) { result.addAll(func.apply(e)); } return result; } public IntList flatMapToInt(final Try.Function, E> func) throws E { N.checkArgNotNull(func); final IntList result = new IntList(size() > N.MAX_ARRAY_SIZE / 2 ? N.MAX_ARRAY_SIZE : size() * 2); if (N.isNullOrEmpty(coll)) { return result; } for (T e : coll) { for (int b : func.apply(e)) { result.add(b); } } return result; } public IntList flattMapToInt(final Try.Function func) throws E { N.checkArgNotNull(func); final IntList result = new IntList(size() > N.MAX_ARRAY_SIZE / 2 ? N.MAX_ARRAY_SIZE : size() * 2); if (N.isNullOrEmpty(coll)) { return result; } for (T e : coll) { result.addAll(func.apply(e)); } return result; } public LongList flatMapToLong(final Try.Function, E> func) throws E { N.checkArgNotNull(func); final LongList result = new LongList(size() > N.MAX_ARRAY_SIZE / 2 ? N.MAX_ARRAY_SIZE : size() * 2); if (N.isNullOrEmpty(coll)) { return result; } for (T e : coll) { for (long b : func.apply(e)) { result.add(b); } } return result; } public LongList flattMapToLong(final Try.Function func) throws E { N.checkArgNotNull(func); final LongList result = new LongList(size() > N.MAX_ARRAY_SIZE / 2 ? N.MAX_ARRAY_SIZE : size() * 2); if (N.isNullOrEmpty(coll)) { return result; } for (T e : coll) { result.addAll(func.apply(e)); } return result; } public FloatList flatMapToFloat(final Try.Function, E> func) throws E { N.checkArgNotNull(func); final FloatList result = new FloatList(size() > N.MAX_ARRAY_SIZE / 2 ? N.MAX_ARRAY_SIZE : size() * 2); if (N.isNullOrEmpty(coll)) { return result; } for (T e : coll) { for (float b : func.apply(e)) { result.add(b); } } return result; } public FloatList flattMapToFloat(final Try.Function func) throws E { N.checkArgNotNull(func); final FloatList result = new FloatList(size() > N.MAX_ARRAY_SIZE / 2 ? N.MAX_ARRAY_SIZE : size() * 2); if (N.isNullOrEmpty(coll)) { return result; } for (T e : coll) { result.addAll(func.apply(e)); } return result; } public DoubleList flatMapToDouble(final Try.Function, E> func) throws E { N.checkArgNotNull(func); final DoubleList result = new DoubleList(size() > N.MAX_ARRAY_SIZE / 2 ? N.MAX_ARRAY_SIZE : size() * 2); if (N.isNullOrEmpty(coll)) { return result; } for (T e : coll) { for (double b : func.apply(e)) { result.add(b); } } return result; } public DoubleList flattMapToDouble(final Try.Function func) throws E { N.checkArgNotNull(func); final DoubleList result = new DoubleList(size() > N.MAX_ARRAY_SIZE / 2 ? N.MAX_ARRAY_SIZE : size() * 2); if (N.isNullOrEmpty(coll)) { return result; } for (T e : coll) { result.addAll(func.apply(e)); } return result; } public List flatMap(final Try.Function, E> mapper, final Try.BiFunction func) throws E, E2 { N.checkArgNotNull(mapper); N.checkArgNotNull(func); final List result = new ArrayList(N.max(9, coll.size())); for (T e : coll) { final Collection c = mapper.apply(e); if (N.notNullOrEmpty(c)) { for (U u : c) { result.add(func.apply(e, u)); } } } return result; } public List flatMap( final Try.Function, E> mapper2, final Try.Function, E2> mapper3, final Try.TriFunction func) throws E, E2, E3 { N.checkArgNotNull(mapper2); N.checkArgNotNull(mapper3); N.checkArgNotNull(func); if (N.isNullOrEmpty(coll)) { return new ArrayList(); } final List result = new ArrayList(N.max(9, coll.size())); for (T e : coll) { final Collection c2 = mapper2.apply(e); if (N.notNullOrEmpty(c2)) { for (T2 t2 : c2) { final Collection c3 = mapper3.apply(t2); if (N.notNullOrEmpty(c3)) { for (T3 t3 : c3) { result.add(func.apply(e, t2, t3)); } } } } } return result; } /** * For better performance, comparing to {@code Stream}. * * @param filter * @param mapper * @return * @throws E * @throws E2 */ @Beta public List filterThenMap(final Try.Predicate filter, final Try.Function mapper) throws E, E2 { N.checkArgNotNull(filter); N.checkArgNotNull(mapper); final List result = new ArrayList<>(); for (T e : coll) { if (filter.test(e)) { result.add(mapper.apply(e)); } } return result; } /** * For better performance, comparing to {@code Stream}. * * @param filter * @param mapper * @return * @throws E * @throws E2 */ @Beta public List filterThenFlatMap(final Try.Predicate filter, final Try.Function, E2> mapper) throws E, E2 { N.checkArgNotNull(filter); N.checkArgNotNull(mapper); final List result = new ArrayList<>(); Collection c = null; for (T e : coll) { if (filter.test(e)) { c = mapper.apply(e); if (N.notNullOrEmpty(c)) { result.addAll(c); } } } return result; } /** * For better performance, comparing to {@code Stream}. * * @param mapper * @param filter * @return * @throws E * @throws E2 */ @Beta public List mapThenFilter(final Try.Function mapper, final Try.Predicate filter) throws E, E2 { N.checkArgNotNull(mapper); N.checkArgNotNull(filter); final List result = new ArrayList<>(); R r = null; for (T e : coll) { r = mapper.apply(e); if (filter.test(r)) { result.add(r); } } return result; } /** * For better performance, comparing to {@code Stream}. * * @param mapper * @param filter * @return * @throws E * @throws E2 */ @Beta public List flatMapThenFilter(final Try.Function, E> mapper, final Try.Predicate filter) throws E, E2 { N.checkArgNotNull(mapper); N.checkArgNotNull(filter); final List result = new ArrayList<>(); Collection c = null; for (T e : coll) { c = mapper.apply(e); if (N.notNullOrEmpty(c)) { for (R r : c) { if (filter.test(r)) { result.add(r); } } } } return result; } /** * For better performance, comparing to {@code Stream}. * * @param filter * @param action * @return * @throws E * @throws E2 */ @Beta public void filterThenForEach(final Try.Predicate filter, final Try.Consumer action) throws E, E2 { N.checkArgNotNull(filter); N.checkArgNotNull(action); for (T e : coll) { if (filter.test(e)) { action.accept(e); } } } /** * For better performance, comparing to {@code Stream}. * * @param mapper * @param action * @return * @throws E * @throws E2 */ @Beta public void mapThenForEach(final Try.Function mapper, final Try.Consumer action) throws E, E2 { N.checkArgNotNull(mapper); N.checkArgNotNull(action); for (T e : coll) { action.accept(mapper.apply(e)); } } /** * For better performance, comparing to {@code Stream}. * * @param mapper * @param action * @return * @throws E * @throws E2 */ @Beta public void flatMapThenForEach(final Try.Function, E> mapper, final Try.Consumer action) throws E, E2 { N.checkArgNotNull(mapper); N.checkArgNotNull(action); Collection c = null; for (T e : coll) { c = mapper.apply(e); if (N.notNullOrEmpty(c)) { for (R r : c) { action.accept(r); } } } } /** * Merge series of adjacent elements which satisfy the given predicate using the merger function. * *

Example: *

     * 
     * Seq.of(new Integer[0]).collapse((a, b) -> a < b, (a, b) -> a + b) => []
     * Seq.of(1).collapse((a, b) -> a < b, (a, b) -> a + b) => [1]
     * Seq.of(1, 2).collapse((a, b) -> a < b, (a, b) -> a + b) => [3]
     * Seq.of(1, 2, 3).collapse((a, b) -> a < b, (a, b) -> a + b) => [6]
     * Seq.of(1, 2, 3, 3, 2, 1).collapse((a, b) -> a < b, (a, b) -> a + b) => [6, 3, 2, 1]
     * 
     * 
* * @param collapsible * @param mergeFunction * @return */ public List collapse(final Try.BiPredicate collapsible, final Try.BiFunction mergeFunction) throws E, E2 { N.checkArgNotNull(collapsible); N.checkArgNotNull(mergeFunction); final List result = new ArrayList<>(); final Iterator iter = iterator(); boolean hasNext = false; T next = null; while (hasNext || iter.hasNext()) { T res = hasNext ? next : (next = iter.next()); while ((hasNext = iter.hasNext())) { if (collapsible.test(next, (next = iter.next()))) { res = mergeFunction.apply(res, next); } else { break; } } result.add(res); } return result; } public List collapse(final Try.BiPredicate collapsible, final U init, final Try.BiFunction op) throws E, E2 { N.checkArgNotNull(collapsible); N.checkArgNotNull(op); final List result = new ArrayList<>(); final Iterator iter = iterator(); boolean hasNext = false; T next = null; while (hasNext || iter.hasNext()) { U res = op.apply(init, hasNext ? next : (next = iter.next())); while ((hasNext = iter.hasNext())) { if (collapsible.test(next, (next = iter.next()))) { res = op.apply(res, next); } else { break; } } result.add(res); } return result; } public List> collapse(final Try.BiPredicate collapsible) throws E { return collapse(collapsible, Suppliers. ofList()); } public , E extends Exception> List collapse(final Try.BiPredicate collapsible, final Supplier collectionSupplier) throws E { N.checkArgNotNull(collapsible); N.checkArgNotNull(collectionSupplier); final List result = new ArrayList<>(); final Iterator iter = iterator(); boolean hasNext = false; T next = null; while (hasNext || iter.hasNext()) { final C c = collectionSupplier.get(); c.add(hasNext ? next : (next = iter.next())); while ((hasNext = iter.hasNext())) { if (collapsible.test(next, (next = iter.next()))) { c.add(next); } else { break; } } result.add(c); } return result; } /** * Merge series of adjacent elements which satisfy the given predicate using the merger function. * *

Example: *

     * 
     * Seq.of(new Integer[0]).collapse((a, b) -> a < b, Collectors.summingInt(Fn.unboxI())) => []
     * Seq.of(1).collapse((a, b) -> a < b, Collectors.summingInt(Fn.unboxI())) => [1]
     * Seq.of(1, 2).collapse((a, b) -> a < b, Collectors.summingInt(Fn.unboxI())) => [3]
     * Seq.of(1, 2, 3).collapse((a, b) -> a < b, Collectors.summingInt(Fn.unboxI())) => [6]
     * Seq.of(1, 2, 3, 3, 2, 1).collapse((a, b) -> a < b, Collectors.summingInt(Fn.unboxI())) => [6, 3, 2, 1]
     * 
     * 
* * @param collapsible * @param collector * @return */ public List collapse(final Try.BiPredicate collapsible, final Collector collector) throws E { N.checkArgNotNull(collapsible); N.checkArgNotNull(collector); final List result = new ArrayList<>(); final Supplier supplier = collector.supplier(); final BiConsumer accumulator = collector.accumulator(); final Function finisher = collector.finisher(); final Iterator iter = iterator(); boolean hasNext = false; T next = null; while (hasNext || iter.hasNext()) { final A c = supplier.get(); accumulator.accept(c, hasNext ? next : (next = iter.next())); while ((hasNext = iter.hasNext())) { if (collapsible.test(next, (next = iter.next()))) { accumulator.accept(c, next); } else { break; } } result.add(finisher.apply(c)); } return result; } /** * Returns a {@code Stream} produced by iterative application of a accumulation function * to an initial element {@code identity} and next element of the current stream. * Produces a {@code Stream} consisting of {@code identity}, {@code acc(identity, value1)}, * {@code acc(acc(identity, value1), value2)}, etc. * *

Example: *

     * 
     * Seq.of(new Integer[0]).scan((a, b) -> a + b) => []
     * Seq.of(1).scan((a, b) -> a + b) => [1]
     * Seq.of(1, 2).scan((a, b) -> a + b) => [1, 3]
     * Seq.of(1, 2, 3).scan((a, b) -> a + b) => [1, 3, 6]
     * Seq.of(1, 2, 3, 3, 2, 1).scan((a, b) -> a + b) => [1, 3, 6, 9, 11, 12]
     * 
     * 
* * @param accumulator the accumulation function * @return */ public List scan(final Try.BiFunction accumulator) throws E { N.checkArgNotNull(accumulator); final List result = new ArrayList<>(); final Iterator iter = iterator(); T next = null; if (iter.hasNext()) { result.add((next = iter.next())); } while (iter.hasNext()) { result.add((next = accumulator.apply(next, iter.next()))); } return result; } /** * Returns a {@code Stream} produced by iterative application of a accumulation function * to an initial element {@code identity} and next element of the current stream. * Produces a {@code Stream} consisting of {@code identity}, {@code acc(identity, value1)}, * {@code acc(acc(identity, value1), value2)}, etc. * *

Example: *

     * 
     * Seq.of(new Integer[0]).scan(10, (a, b) -> a + b) => []
     * Seq.of(1).scan(10, (a, b) -> a + b) => [11]
     * Seq.of(1, 2).scan(10, (a, b) -> a + b) => [11, 13]
     * Seq.of(1, 2, 3).scan(10, (a, b) -> a + b) => [11, 13, 16]
     * Seq.of(1, 2, 3, 3, 2, 1).scan(10, (a, b) -> a + b) => [11, 13, 16, 19, 21, 22]
     * 
     * 
* * @param init the initial value. it's only used once by accumulator to calculate the fist element in the returned stream. * It will be ignored if this stream is empty and won't be the first element of the returned stream. * * @param accumulator the accumulation function * @return */ public List scan(final U init, final Try.BiFunction accumulator) throws E { return scan(init, accumulator, false); } /** * * @param init * @param accumulator * @param initIncluded * @return * @throws E */ public List scan(final U init, final Try.BiFunction accumulator, boolean initIncluded) throws E { N.checkArgNotNull(accumulator); final List result = new ArrayList<>(); if (initIncluded) { result.add(init); } final Iterator iter = iterator(); U next = init; while (iter.hasNext()) { result.add((next = accumulator.apply(next, iter.next()))); } return result; } /** * This is equivalent to: *
     * 
     *    if (isEmpty()) {
     *        return Nullable.empty();
     *    }
     *
     *    final Iterator iter = iterator();
     *    T result = iter.next();
     *
     *    while (iter.hasNext()) {
     *        result = accumulator.apply(result, iter.next());
     *    }
     *
     *    return Nullable.of(result);
     * 
     * 
* * @param accumulator * @return */ public Nullable reduce(Try.BinaryOperator accumulator) throws E { N.checkArgNotNull(accumulator); if (isEmpty()) { return Nullable.empty(); } final Iterator iter = iterator(); T result = iter.next(); while (iter.hasNext()) { result = accumulator.apply(result, iter.next()); } return Nullable.of(result); } /** * This is equivalent to: *
     * 
     *     if (isEmpty()) {
     *         return identity;
     *     }
     * 
     *     final Iterator iter =  iterator();
     *     U result = identity;
     * 
     *     while (iter.hasNext()) {
     *         result = accumulator.apply(result, iter.next());
     *     }
     * 
     *     return result;
     * 
     * 
* * @param identity * @param accumulator * @return */ public U reduce(final U identity, final Try.BiFunction accumulator) throws E { N.checkArgNotNull(accumulator); if (isEmpty()) { return identity; } final Iterator iter = iterator(); U result = identity; while (iter.hasNext()) { result = accumulator.apply(result, iter.next()); } return result; } public R collect(final Supplier supplier, final Try.BiConsumer accumulator) throws E { N.checkArgNotNull(supplier); N.checkArgNotNull(accumulator); final R result = supplier.get(); for (T e : coll) { accumulator.accept(result, e); } return result; } public R collect(final Supplier
supplier, final Try.BiConsumer accumulator, final Try.Function finisher) throws E, E2 { N.checkArgNotNull(supplier); N.checkArgNotNull(accumulator); N.checkArgNotNull(finisher); final A result = supplier.get(); for (T e : coll) { accumulator.accept(result, e); } return finisher.apply(result); } public R collect(final Collector collector) { N.checkArgNotNull(collector); final BiConsumer accumulator = collector.accumulator(); final A result = collector.supplier().get(); for (T e : coll) { accumulator.accept(result, e); } return collector.finisher().apply(result); } public R collect(final java.util.stream.Collector collector) { N.checkArgNotNull(collector); final java.util.function.BiConsumer accumulator = collector.accumulator(); final A result = collector.supplier().get(); for (T e : coll) { accumulator.accept(result, e); } return collector.finisher().apply(result); } public RR collectThenApply(final Collector downstream, final Try.Function mapper) throws E { return mapper.apply(collect(downstream)); } public RR collectThenApply(final java.util.stream.Collector downstream, final Try.Function mapper) throws E { return mapper.apply(collect(downstream)); } public void collectThenAccept(final Collector downstream, final Try.Consumer consumer) throws E { consumer.accept(collect(downstream)); } public void collectThenAccept(final java.util.stream.Collector downstream, final Try.Consumer consumer) throws E { consumer.accept(collect(downstream)); } @SafeVarargs public final List append(T... a) { if (N.isNullOrEmpty(a)) { return toList(); } return append(Arrays.asList(a)); } public List append(final Collection c) { return N.concat(this, c); } @SafeVarargs public final List prepend(T... a) { if (N.isNullOrEmpty(a)) { return toList(); } return prepend(Arrays.asList(a)); } public List prepend(final Collection c) { return N.concat(c, this); } public List merge(final Collection b, final Try.BiFunction nextSelector) throws E { return N.merge(this, b, nextSelector); } public List zipWith(final Collection b, final Try.BiFunction zipFunction) throws E { return N.zip(this, b, zipFunction); } public List zipWith(final Collection b, final T valueForNoneA, final B valueForNoneB, final Try.BiFunction zipFunction) throws E { return N.zip(this, b, valueForNoneA, valueForNoneB, zipFunction); } public List zipWith(final Collection b, final Collection c, final Try.TriFunction zipFunction) throws E { return N.zip(this, b, c, zipFunction); } public List zipWith(final Collection b, final Collection c, final T valueForNoneA, final B valueForNoneB, final C valueForNoneC, final Try.TriFunction zipFunction) throws E { return N.zip(this, b, c, valueForNoneA, valueForNoneB, valueForNoneC, zipFunction); } public List intersperse(T value) { if (isEmpty()) { return new ArrayList<>(); } final int size = size(); final List result = new ArrayList<>(size * 2 - 1); int idx = 0; for (T e : coll) { result.add(e); if (++idx < size) { result.add(value); } } return result; } public List> indexed() { final List> result = new ArrayList<>(size()); int idx = 0; for (T e : coll) { result.add(Indexed.of(e, idx++)); } return result; } /** * * @return a new List with distinct elements */ public List distinct() { return N.distinct(coll); } /** * * @param keyMapper don't change value of the input parameter. * @return */ public List distinctBy(final Try.Function keyMapper) throws E { return N.distinctBy(coll, keyMapper); } @SuppressWarnings("rawtypes") public List top(final int n) { return N.top((Collection) coll, n); } public List top(final int n, final Comparator cmp) { return N.top(coll, n, cmp); } /** * Returns consecutive sub lists of this list, each of the same size (the final list may be smaller), * or an empty List if the specified list is null or empty. * * @param chunkSize the desired size of each sub sequence (the last may be smaller). * @return */ public List> split(int chunkSize) { return N.split(coll, chunkSize); } public List> split(final Try.Predicate predicate) throws E { return split(predicate, Suppliers. ofList()); } public , E extends Exception> List split(final Try.Predicate predicate, final Supplier supplier) throws E { N.checkArgNotNull(predicate); N.checkArgNotNull(supplier); final List res = new ArrayList<>(); final Iterator elements = iterator(); final T NONE = (T) N.NULL_MASK; T next = NONE; boolean preCondition = false; while (next != NONE || elements.hasNext()) { final C piece = supplier.get(); if (next == NONE) { next = elements.next(); } while (next != NONE) { if (piece.size() == 0) { piece.add(next); preCondition = predicate.test(next); next = elements.hasNext() ? elements.next() : NONE; } else if (predicate.test(next) == preCondition) { piece.add(next); next = elements.hasNext() ? elements.next() : NONE; } else { break; } } res.add(piece); } return res; } /** * *
     * 
     * // split the number sequence by window 5.
     * Seq.of(1, 2, 3, 5, 7, 9, 10, 11, 19).split(MutableInt.of(5), (e, b) -> e <= b.intValue(), b -> b.addAndGet(5)).forEach(N::println);
     * 
     * 
* * @param flag * @param predicate * @param flagUpdate * @return * @throws E * @throws E2 */ public List> split(final U flag, final Try.BiPredicate predicate, final Try.Consumer flagUpdate) throws E, E2 { return split(flag, predicate, flagUpdate, Suppliers. ofList()); } /** * * @param flag * @param predicate * @param flagUpdate * @param supplier * @return * @throws E * @throws E2 */ public , E extends Exception, E2 extends Exception> List split(final U flag, final Try.BiPredicate predicate, final Try.Consumer flagUpdate, final Supplier supplier) throws E, E2 { N.checkArgNotNull(predicate); N.checkArgNotNull(flagUpdate); N.checkArgNotNull(supplier); final List res = new ArrayList<>(); final Iterator elements = iterator(); final T NONE = (T) N.NULL_MASK; T next = NONE; boolean preCondition = false; while (next != NONE || elements.hasNext()) { final C piece = supplier.get(); if (next == NONE) { next = elements.next(); } while (next != NONE) { if (piece.size() == 0) { piece.add(next); preCondition = predicate.test(next, flag); next = elements.hasNext() ? elements.next() : NONE; } else if (predicate.test(next, flag) == preCondition) { piece.add(next); next = elements.hasNext() ? elements.next() : NONE; } else { if (flagUpdate != null) { flagUpdate.accept(flag); } break; } } res.add(piece); } return res; } /** * * @param where * @return */ @SuppressWarnings("rawtypes") public Pair, List> splitAt(final int where) { N.checkArgNotNegative(where, "where"); List left = null; List right = null; if (N.isNullOrEmpty(coll)) { left = new ArrayList<>(); right = new ArrayList<>(); } else if (where == 0) { left = new ArrayList<>(); right = new ArrayList<>(coll); } else if (where >= coll.size()) { left = new ArrayList<>(); right = new ArrayList<>(coll); } else if (coll instanceof List) { left = new ArrayList<>(((List) coll).subList(0, where)); right = new ArrayList<>(((List) coll).subList(where, size())); } else { left = new ArrayList<>(where); right = new ArrayList<>(coll.size() - where); final Iterator iter = coll.iterator(); int cnt = 0; while (cnt++ < where) { left.add(iter.next()); } while (iter.hasNext()) { right.add(iter.next()); } } return Pair.of(left, right); } public Pair, List> splitBy(final Try.Predicate predicate) throws E { N.checkArgNotNull(predicate); final List left = new ArrayList<>(); final List right = new ArrayList<>(); final Iterator iter = iterator(); T next = (T) N.NULL_MASK; while (iter.hasNext() && predicate.test((next = iter.next()))) { left.add(next); next = (T) N.NULL_MASK; } if (next != N.NULL_MASK) { right.add(next); } while (iter.hasNext()) { right.add(iter.next()); } return Pair.of(left, right); } public List> sliding(final int windowSize) { return sliding(windowSize, 1); } public List> sliding(final int windowSize, final int increment) { N.checkArgument(windowSize > 0 && increment > 0, "windowSize=%s and increment=%s must be bigger than 0", windowSize, increment); final Iterator iter = coll.iterator(); final List> result = new ArrayList<>(coll.size() <= windowSize ? 1 : (1 + (coll.size() - windowSize)) / increment); while (iter.hasNext()) { if (increment > windowSize && result.size() > 0) { int skipNum = increment - windowSize; while (skipNum-- > 0 && iter.hasNext()) { iter.next(); } if (iter.hasNext() == false) { break; } } final List window = new ArrayList<>(windowSize); int cnt = 0; if (increment < windowSize && result.size() > 0) { final List prev = result.get(result.size() - 1); cnt = windowSize - increment; if (cnt <= 8) { for (int i = windowSize - cnt; i < windowSize; i++) { window.add(prev.get(i)); } } else { window.addAll(prev.subList(windowSize - cnt, windowSize)); } } while (cnt++ < windowSize && iter.hasNext()) { window.add(iter.next()); } result.add(window); } return result; } public String join() { return join(N.ELEMENT_SEPARATOR); } public String join(final char delimiter) { return StringUtil.join(coll, delimiter); } public String join(final String delimiter) { return StringUtil.join(coll, delimiter); } public String join(final Try.Function toStringFunc, final String delimiter) throws E { if (N.isNullOrEmpty(coll)) { return N.EMPTY_STRING; } try (final Joiner joiner = Joiner.with(delimiter).reuseCachedBuffer(true)) { for (T e : coll) { joiner.append(e); } return joiner.toString(); } } /** * * @return * @throws DuplicatedResultException if there are more than one element in this {@code Seq}. */ public Nullable onlyOne() throws DuplicatedResultException { if (isEmpty()) { return Nullable.empty(); } else if (size() == 1) { return first(); } else { throw new DuplicatedResultException(N.toString(coll)); } } @Override public boolean isEmpty() { return coll == null || coll.isEmpty(); } @Override public int size() { return coll == null ? 0 : coll.size(); } @Override public Object[] toArray() { return coll == null ? N.EMPTY_OBJECT_ARRAY : coll.toArray(); } @Override public
A[] toArray(A[] a) { return coll == null ? a : coll.toArray(a); } public List toList() { return coll == null ? new ArrayList() : new ArrayList(coll); } public Set toSet() { return coll == null ? new HashSet() : new HashSet(coll); } public > C toCollection(final IntFunction supplier) { final C result = supplier.apply(size()); if (N.notNullOrEmpty(coll)) { result.addAll(coll); } return result; } public Multiset toMultiset() { final Multiset result = new Multiset<>(N.initHashCapacity(size())); if (N.notNullOrEmpty(coll)) { result.addAll(coll); } return result; } public Multiset toMultiset(final IntFunction> supplier) { final Multiset result = supplier.apply(size()); if (N.notNullOrEmpty(coll)) { result.addAll(coll); } return result; } public Map toMap(Try.Function keyMapper, Try.Function valueMapper) throws E, E2 { return toMap(keyMapper, valueMapper, Factory. ofMap()); } public , E extends Exception, E2 extends Exception> M toMap(Try.Function keyMapper, Try.Function valueMapper, IntFunction mapFactory) throws E, E2 { return toMap(keyMapper, valueMapper, Fn. throwingMerger(), mapFactory); } public Map toMap(Try.Function keyMapper, Try.Function valueMapper, Try.BinaryOperator mergeFunction) throws E, E2, E3 { return toMap(keyMapper, valueMapper, mergeFunction, Factory. ofMap()); } public , E extends Exception, E2 extends Exception, E3 extends Exception> M toMap( Try.Function keyMapper, Try.Function valueMapper, Try.BinaryOperator mergeFunction, IntFunction mapFactory) throws E, E2, E3 { final M result = mapFactory.apply(size()); for (T e : coll) { Maps.merge(result, keyMapper.apply(e), valueMapper.apply(e), mergeFunction); } return result; } public Map toMap(Try.Function keyMapper, Collector downstream) throws E { return toMap(keyMapper, downstream, Factory. ofMap()); } public , E extends Exception> M toMap(final Try.Function keyMapper, final Collector downstream, final IntFunction mapFactory) throws E { return toMap(keyMapper, FN. identity(), downstream, mapFactory); } public Map toMap(Try.Function keyMapper, Try.Function valueMapper, Collector downstream) throws E, E2 { return toMap(keyMapper, valueMapper, downstream, Factory. ofMap()); } public , E extends Exception, E2 extends Exception> M toMap(final Try.Function keyMapper, Try.Function valueMapper, final Collector downstream, final IntFunction mapFactory) throws E, E2 { final M result = mapFactory.apply(size()); final Supplier downstreamSupplier = downstream.supplier(); final BiConsumer downstreamAccumulator = downstream.accumulator(); final Map intermediate = (Map) result; K key = null; A v = null; for (T e : coll) { key = N.checkArgNotNull(keyMapper.apply(e), "element cannot be mapped to a null key"); if ((v = intermediate.get(key)) == null) { if ((v = downstreamSupplier.get()) != null) { intermediate.put(key, v); } } downstreamAccumulator.accept(v, valueMapper.apply(e)); } final BiFunction function = new BiFunction() { @Override public A apply(K k, A v) { return (A) downstream.finisher().apply(v); } }; Maps.replaceAll(intermediate, function); return result; } public Map flatToMap(Try.Function, E> flatKeyMapper, Try.BiFunction valueMapper) throws E, E2 { return flatToMap(flatKeyMapper, valueMapper, Factory. ofMap()); } public , E extends Exception, E2 extends Exception> M flatToMap( Try.Function, E> flatKeyMapper, Try.BiFunction valueMapper, IntFunction mapFactory) throws E, E2 { return flatToMap(flatKeyMapper, valueMapper, Fn. throwingMerger(), mapFactory); } public Map flatToMap( Try.Function, E> flatKeyMapper, Try.BiFunction valueMapper, Try.BinaryOperator mergeFunction) throws E, E2, E3 { return flatToMap(flatKeyMapper, valueMapper, mergeFunction, Factory. ofMap()); } public , E extends Exception, E2 extends Exception, E3 extends Exception> M flatToMap( Try.Function, E> flatKeyMapper, Try.BiFunction valueMapper, Try.BinaryOperator mergeFunction, IntFunction mapFactory) throws E, E2, E3 { final M result = mapFactory.apply(size()); Collection keys = null; for (T e : coll) { keys = flatKeyMapper.apply(e); if (N.notNullOrEmpty(keys)) { for (K k : keys) { Maps.merge(result, k, valueMapper.apply(k, e), mergeFunction); } } } return result; } public Map flatToMap(Try.Function, E> flatKeyMapper, Collector downstream) throws E { return flatToMap(flatKeyMapper, downstream, Factory. ofMap()); } public , E extends Exception> Map flatToMap(Try.Function, E> flatKeyMapper, Collector downstream, final IntFunction mapFactory) throws E { return flatToMap(flatKeyMapper, BiFunctions. returnSecond(), downstream, mapFactory); } public Map flatToMap( Try.Function, E> flatKeyMapper, Try.BiFunction valueMapper, Collector downstream) throws E, E2 { return flatToMap(flatKeyMapper, valueMapper, downstream, Factory. ofMap()); } public , E extends Exception, E2 extends Exception> M flatToMap( Try.Function, E> flatKeyMapper, Try.BiFunction valueMapper, final Collector downstream, final IntFunction mapFactory) throws E, E2 { final M result = mapFactory.apply(size()); final Supplier downstreamSupplier = downstream.supplier(); final BiConsumer downstreamAccumulator = downstream.accumulator(); final Map intermediate = (Map) result; Collection keys = null; A v = null; for (T e : coll) { keys = flatKeyMapper.apply(e); if (N.notNullOrEmpty(keys)) { for (K k : keys) { N.checkArgNotNull(k, "element cannot be mapped to a null key"); if ((v = intermediate.get(k)) == null) { if ((v = downstreamSupplier.get()) != null) { intermediate.put(k, v); } } downstreamAccumulator.accept(v, valueMapper.apply(k, e)); } } } final BiFunction function = new BiFunction() { @Override public A apply(K k, A v) { return (A) downstream.finisher().apply(v); } }; Maps.replaceAll(intermediate, function); return result; } public Map> groupTo(Try.Function keyMapper) throws E { return groupTo(keyMapper, Factory.> ofMap()); } public >, E extends Exception> M groupTo(Try.Function keyMapper, IntFunction mapFactory) throws E { final M result = mapFactory.apply(size()); K key = null; List values = null; for (T e : coll) { key = keyMapper.apply(e); values = result.get(key); if (values == null) { values = new ArrayList<>(); result.put(key, values); } values.add(e); } return result; } public Map> groupTo(Try.Function keyMapper, Try.Function valueMapper) throws E, E2 { return groupTo(keyMapper, valueMapper, Factory.> ofMap()); } public >, E extends Exception, E2 extends Exception> M groupTo(Try.Function keyMapper, Try.Function valueMapper, IntFunction mapFactory) throws E, E2 { final M result = mapFactory.apply(size()); K key = null; List values = null; for (T e : coll) { key = keyMapper.apply(e); values = result.get(key); if (values == null) { values = new ArrayList<>(); result.put(key, values); } values.add(valueMapper.apply(e)); } return result; } public Map> flatGroupTo(final Try.Function, E> flatKeyMapper) throws E { return flatGroupTo(flatKeyMapper, Factory.> ofMap()); } public >, E extends Exception> M flatGroupTo(final Try.Function, E> flatKeyMapper, final IntFunction mapFactory) throws E { final M result = mapFactory.apply(size()); Collection keys = null; List values = null; for (T e : coll) { keys = flatKeyMapper.apply(e); if (N.notNullOrEmpty(keys)) { for (K k : keys) { values = result.get(k); if (values == null) { values = new ArrayList<>(); result.put(k, values); } values.add(e); } } } return result; } public Map> flatGroupTo( final Try.Function, E> flatKeyMapper, final Try.BiFunction valueMapper) throws E, E2 { return flatGroupTo(flatKeyMapper, valueMapper, Factory.> ofMap()); } public >, E extends Exception, E2 extends Exception> M flatGroupTo( final Try.Function, E> flatKeyMapper, final Try.BiFunction valueMapper, final IntFunction mapFactory) throws E, E2 { final M result = mapFactory.apply(size()); Collection keys = null; List values = null; for (T e : coll) { keys = flatKeyMapper.apply(e); if (N.notNullOrEmpty(keys)) { for (K k : keys) { values = result.get(k); if (values == null) { values = new ArrayList<>(); result.put(k, values); } values.add(valueMapper.apply(k, e)); } } } return result; } /** * * @param keyMapper * @return */ public ListMultimap toMultimap(Try.Function keyMapper) throws E { return toMultimap(keyMapper, Factory. ofListMultimap()); } public , M extends Multimap, E extends Exception> M toMultimap(Try.Function keyMapper, IntFunction mapFactory) throws E { final M result = mapFactory.apply(size()); for (T e : coll) { result.put(keyMapper.apply(e), e); } return result; } /** * * @param keyMapper * @param valueMapper * @return */ public ListMultimap toMultimap(Try.Function keyMapper, Try.Function valueMapper) throws E, E2 { return toMultimap(keyMapper, valueMapper, Factory. ofListMultimap()); } public , M extends Multimap, E extends Exception, E2 extends Exception> M toMultimap( Try.Function keyMapper, Try.Function valueMapper, IntFunction mapFactory) throws E, E2 { final M result = mapFactory.apply(size()); for (T e : coll) { result.put(keyMapper.apply(e), valueMapper.apply(e)); } return result; } /** * * @param flatKeyMapper * @return */ public ListMultimap flatToMultimap(Try.Function, E> flatKeyMapper) throws E { return flatToMultimap(flatKeyMapper, Factory. ofListMultimap()); } public , M extends Multimap, E extends Exception> M flatToMultimap( Try.Function, E> flatKeyMapper, IntFunction mapFactory) throws E { final M result = mapFactory.apply(size()); Collection ks = null; for (T e : coll) { ks = flatKeyMapper.apply(e); if (N.notNullOrEmpty(ks)) { for (K k : ks) { result.put(k, e); } } } return result; } /** * * @param flatKeyMapper * @param valueMapper * @return */ public ListMultimap flatToMultimap( Try.Function, E> flatKeyMapper, Try.BiFunction valueMapper) throws E, E2 { return flatToMultimap(flatKeyMapper, valueMapper, Factory. ofListMultimap()); } public , M extends Multimap, E extends Exception, E2 extends Exception> M flatToMultimap( Try.Function, E> flatKeyMapper, Try.BiFunction valueMapper, IntFunction mapFactory) throws E, E2 { final M result = mapFactory.apply(size()); Collection ks = null; for (T e : coll) { ks = flatKeyMapper.apply(e); if (N.notNullOrEmpty(ks)) { for (K k : ks) { result.put(k, valueMapper.apply(k, e)); } } } return result; } /** * * The time complexity is O(n + m) : n is the size of this Seq and m is the size of specified collection b. * * @param b * @param leftKeyMapper * @param rightKeyMapper * @return * @see sql join */ public List> innerJoin(final Collection b, final Try.Function leftKeyMapper, final Try.Function rightKeyMapper) throws E, E2 { final List> result = new ArrayList<>(N.min(9, size(), N.size(b))); if (N.isNullOrEmpty(coll) || N.isNullOrEmpty(b)) { return result; } final ListMultimap rightKeyMap = ListMultimap.from(b, rightKeyMapper); for (T left : coll) { final List rights = rightKeyMap.get(leftKeyMapper.apply(left)); if (N.notNullOrEmpty(rights)) { for (U right : rights) { result.add(Pair.of(left, right)); } } } return result; } /** * * The time complexity is O(n * m) : n is the size of this Seq and m is the size of specified collection b. * * @param b * @param predicate * @return * @see List> fullJoin(final Collection b, final Try.Function leftKeyMapper, final Try.Function rightKeyMapper) throws E, E2 { final List> result = new ArrayList<>(N.max(9, size(), N.size(b))); if (N.isNullOrEmpty(coll)) { for (T left : coll) { result.add(Pair.of(left, (U) null)); } } else if (N.isNullOrEmpty(b)) { for (U right : b) { result.add(Pair.of((T) null, right)); } } else { final ListMultimap rightKeyMap = ListMultimap.from(b, rightKeyMapper); final Map joinedRights = new IdentityHashMap<>(); for (T left : coll) { final List rights = rightKeyMap.get(leftKeyMapper.apply(left)); if (N.notNullOrEmpty(rights)) { for (U right : rights) { result.add(Pair.of(left, right)); joinedRights.put(right, right); } } else { result.add(Pair.of(left, (U) null)); } } for (U right : b) { if (joinedRights.containsKey(right) == false) { result.add(Pair.of((T) null, right)); } } } return result; } /** * The time complexity is O(n * m) : n is the size of this Seq and m is the size of specified collection b. * * @param b * @param predicate * @return * @see List> leftJoin(final Collection b, final Try.Function leftKeyMapper, final Try.Function rightKeyMapper) throws E, E2 { final List> result = new ArrayList<>(size()); if (N.isNullOrEmpty(coll)) { return result; } else if (N.isNullOrEmpty(b)) { for (T left : coll) { result.add(Pair.of(left, (U) null)); } } else { final ListMultimap rightKeyMap = ListMultimap.from(b, rightKeyMapper); for (T left : coll) { final List rights = rightKeyMap.get(leftKeyMapper.apply(left)); if (N.notNullOrEmpty(rights)) { for (U right : rights) { result.add(Pair.of(left, right)); } } else { result.add(Pair.of(left, (U) null)); } } } return result; } /** * The time complexity is O(n * m) : n is the size of this Seq and m is the size of specified collection b. * * @param b * @param predicate * @return * @see List> rightJoin(final Collection b, final Try.Function leftKeyMapper, final Try.Function rightKeyMapper) throws E, E2 { final List> result = new ArrayList<>(N.size(b)); if (N.isNullOrEmpty(b)) { return result; } else if (N.isNullOrEmpty(coll)) { for (U right : b) { result.add(Pair.of((T) null, right)); } } else { final ListMultimap leftKeyMap = ListMultimap.from(coll, leftKeyMapper); for (U right : b) { final List lefts = leftKeyMap.get(rightKeyMapper.apply(right)); if (N.notNullOrEmpty(lefts)) { for (T left : lefts) { result.add(Pair.of(left, right)); } } else { result.add(Pair.of((T) null, right)); } } } return result; } /** * The time complexity is O(n * m) : n is the size of this Seq and m is the size of specified collection b. * * @param b * @param predicate * @return * @see