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

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

/*
 * Copyright (c) 2018, 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.AbstractSet;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.TreeSet;

import com.landawn.abacus.util.u.Nullable;
import com.landawn.abacus.util.u.OptionalByte;
import com.landawn.abacus.util.u.OptionalChar;
import com.landawn.abacus.util.u.OptionalDouble;
import com.landawn.abacus.util.u.OptionalFloat;
import com.landawn.abacus.util.u.OptionalInt;
import com.landawn.abacus.util.u.OptionalLong;
import com.landawn.abacus.util.u.OptionalShort;
import com.landawn.abacus.util.function.Function;

/**
 * 

* Note: This class includes codes copied from Apache Commons Lang, Google Guava and other open source projects under the Apache License 2.0. * The methods copied from other libraries/frameworks/projects may be modified in this class. *

* *

* This is a utility class for iterable data structures, including {@code Collection/Array/Iterator}. *

* *

* The methods in this class should only read the input {@code Collection/Array/Iterator} parameters, not modify them. *

* */ public final class Iterables { Iterables() { // Utility class. } @SafeVarargs public static OptionalChar min(final char... a) { return a == null || a.length == 0 ? OptionalChar.empty() : OptionalChar.of(N.min(a)); } @SafeVarargs public static OptionalByte min(final byte... a) { return a == null || a.length == 0 ? OptionalByte.empty() : OptionalByte.of(N.min(a)); } @SafeVarargs public static OptionalShort min(final short... a) { return a == null || a.length == 0 ? OptionalShort.empty() : OptionalShort.of(N.min(a)); } @SafeVarargs public static OptionalInt min(final int... a) { return a == null || a.length == 0 ? OptionalInt.empty() : OptionalInt.of(N.min(a)); } @SafeVarargs public static OptionalLong min(final long... a) { return a == null || a.length == 0 ? OptionalLong.empty() : OptionalLong.of(N.min(a)); } @SafeVarargs public static OptionalFloat min(final float... a) { return a == null || a.length == 0 ? OptionalFloat.empty() : OptionalFloat.of(N.min(a)); } @SafeVarargs public static OptionalDouble min(final double... a) { return a == null || a.length == 0 ? OptionalDouble.empty() : OptionalDouble.of(N.min(a)); } @SafeVarargs public static OptionalChar max(final char... a) { return a == null || a.length == 0 ? OptionalChar.empty() : OptionalChar.of(N.max(a)); } @SafeVarargs public static OptionalByte max(final byte... a) { return a == null || a.length == 0 ? OptionalByte.empty() : OptionalByte.of(N.max(a)); } @SafeVarargs public static OptionalShort max(final short... a) { return a == null || a.length == 0 ? OptionalShort.empty() : OptionalShort.of(N.max(a)); } @SafeVarargs public static OptionalInt max(final int... a) { return a == null || a.length == 0 ? OptionalInt.empty() : OptionalInt.of(N.max(a)); } @SafeVarargs public static OptionalLong max(final long... a) { return a == null || a.length == 0 ? OptionalLong.empty() : OptionalLong.of(N.max(a)); } @SafeVarargs public static OptionalFloat max(final float... a) { return a == null || a.length == 0 ? OptionalFloat.empty() : OptionalFloat.of(N.max(a)); } @SafeVarargs public static OptionalDouble max(final double... a) { return a == null || a.length == 0 ? OptionalDouble.empty() : OptionalDouble.of(N.max(a)); } public static > Nullable min(final T[] a) { return N.isNullOrEmpty(a) ? Nullable. empty() : Nullable.of(N.min(a)); } public static Nullable min(final T[] a, final Comparator cmp) { return N.isNullOrEmpty(a) ? Nullable. empty() : Nullable.of(N.min(a, cmp)); } public static > Nullable min(final Collection c) { return N.isNullOrEmpty(c) ? Nullable. empty() : Nullable.of(N.min(c)); } public static Nullable min(final Collection c, final Comparator cmp) { return N.isNullOrEmpty(c) ? Nullable. empty() : Nullable.of(N.min(c, cmp)); } public static > Nullable min(final Iterator iter) { return min(iter, N.NULL_MAX_COMPARATOR); } public static Nullable min(final Iterator iter, Comparator cmp) { cmp = cmp == null ? N.NULL_MAX_COMPARATOR : cmp; if (iter == null || iter.hasNext() == false) { return Nullable. empty(); } T candidate = null; T next = null; do { next = iter.next(); if (next == null && cmp == N.NULL_MIN_COMPARATOR) { return Nullable.of(next); } else if (cmp.compare(next, candidate) < 0) { candidate = next; } } while (iter.hasNext()); return Nullable.of(candidate); } @SuppressWarnings("rawtypes") public static Nullable minBy(final T[] a, final Function keyMapper) { return min(a, Fn.comparingBy(keyMapper)); } @SuppressWarnings("rawtypes") public static Nullable minBy(final Collection c, final Function keyMapper) { return min(c, Fn.comparingBy(keyMapper)); } @SuppressWarnings("rawtypes") public static Nullable minBy(final Iterator iter, final Function keyMapper) { return min(iter, Fn.comparingBy(keyMapper)); } public static > Nullable max(final T[] a) { return N.isNullOrEmpty(a) ? Nullable. empty() : Nullable.of(N.max(a)); } public static Nullable max(final T[] a, final Comparator cmp) { return N.isNullOrEmpty(a) ? Nullable. empty() : Nullable.of(N.max(a, cmp)); } public static > Nullable max(final Collection c) { return N.isNullOrEmpty(c) ? Nullable. empty() : Nullable.of(N.max(c)); } public static Nullable max(final Collection c, final Comparator cmp) { return N.isNullOrEmpty(c) ? Nullable. empty() : Nullable.of(N.max(c, cmp)); } public static > Nullable max(final Iterator iter) { return max(iter, N.NULL_MIN_COMPARATOR); } public static Nullable max(final Iterator iter, Comparator cmp) { cmp = cmp == null ? N.NULL_MIN_COMPARATOR : cmp; if (iter == null || iter.hasNext() == false) { return Nullable. empty(); } T candidate = null; T next = null; do { next = iter.next(); if (next == null && cmp == N.NULL_MAX_COMPARATOR) { return Nullable.of(next); } else if (cmp.compare(next, candidate) > 0) { candidate = next; } } while (iter.hasNext()); return Nullable.of(candidate); } @SuppressWarnings("rawtypes") public static Nullable maxBy(final T[] a, final Function keyMapper) { return max(a, Fn.comparingBy(keyMapper)); } @SuppressWarnings("rawtypes") public static Nullable maxBy(final Collection c, final Function keyMapper) { return max(c, Fn.comparingBy(keyMapper)); } @SuppressWarnings("rawtypes") public static Nullable maxBy(final Iterator iter, final Function keyMapper) { return max(iter, Fn.comparingBy(keyMapper)); } public static > Nullable median(final T[] a) { return N.isNullOrEmpty(a) ? Nullable. empty() : Nullable.of(N.median(a)); } public static > Nullable median(final Collection c) { return N.isNullOrEmpty(c) ? Nullable. empty() : Nullable.of(N.median(c)); } public static Nullable median(final T[] a, final Comparator cmp) { return N.isNullOrEmpty(a) ? Nullable. empty() : Nullable.of(N.median(a, cmp)); } public static Nullable median(final Collection c, final Comparator cmp) { return N.isNullOrEmpty(c) ? Nullable. empty() : Nullable.of(N.median(c, cmp)); } @SuppressWarnings("rawtypes") public static Nullable medianBy(final T[] a, final Function keyMapper) { return median(a, Fn.comparingBy(keyMapper)); } @SuppressWarnings("rawtypes") public static Nullable medianBy(final Collection c, final Function keyMapper) { return median(c, Fn.comparingBy(keyMapper)); } public static > Nullable kthLargest(final Collection c, final int k) { return N.isNullOrEmpty(c) ? Nullable. empty() : Nullable.of(N.kthLargest(c, k)); } public static > Nullable kthLargest(final T[] a, final int k) { return N.isNullOrEmpty(a) ? Nullable. empty() : Nullable.of(N.kthLargest(a, k)); } public static Nullable kthLargest(final Collection c, final int k, final Comparator cmp) { return N.isNullOrEmpty(c) ? Nullable. empty() : Nullable.of(N.kthLargest(c, k, cmp)); } public static Nullable kthLargest(final T[] a, final int k, final Comparator cmp) { return N.isNullOrEmpty(a) ? Nullable. empty() : Nullable.of(N.kthLargest(a, k, cmp)); } public static OptionalInt indexOf(final Collection c, final Object objToFind) { return Index.of(c, objToFind); } public static OptionalInt indexOf(final Object[] a, final Object objToFind) { return Index.of(a, objToFind); } public static OptionalInt lastIndexOf(final Collection c, final Object objToFind) { return Index.last(c, objToFind); } public static OptionalInt lastIndexOf(final Object[] a, final Object objToFind) { return Index.last(a, objToFind); } public static OptionalInt findFirstOrLastIndex(final Collection c, final Throwables.Predicate predicateForFirst, final Throwables.Predicate predicateForLast) throws E, E2 { if (N.isNullOrEmpty(c)) { return OptionalInt.empty(); } final OptionalInt res = N.findFirstIndex(c, predicateForFirst); return res.isPresent() ? res : N.findLastIndex(c, predicateForLast); } /** * Find first or last index. * * @param the generic type * @param the element type * @param the generic type * @param a the a * @param predicateForFirst the predicate for first * @param predicateForLast the predicate for last * @return the optional int * @throws E the e * @throws E2 the e2 */ public static OptionalInt findFirstOrLastIndex(final T[] a, final Throwables.Predicate predicateForFirst, final Throwables.Predicate predicateForLast) throws E, E2 { if (N.isNullOrEmpty(a)) { return OptionalInt.empty(); } final OptionalInt res = N.findFirstIndex(a, predicateForFirst); return res.isPresent() ? res : N.findLastIndex(a, predicateForLast); } /** * Find first and last index. * * @param the generic type * @param the element type * @param c the c * @param predicate the predicate * @return the pair * @throws E the e */ public static Pair findFirstAndLastIndex(final Collection c, final Throwables.Predicate predicate) throws E { return findFirstAndLastIndex(c, predicate, predicate); } /** * Find first and last index. * * @param the generic type * @param the element type * @param the generic type * @param c the c * @param predicateForFirst the predicate for first * @param predicateForLast the predicate for last * @return the pair * @throws E the e * @throws E2 the e2 */ public static Pair findFirstAndLastIndex(final Collection c, final Throwables.Predicate predicateForFirst, final Throwables.Predicate predicateForLast) throws E, E2 { if (N.isNullOrEmpty(c)) { return Pair.of(OptionalInt.empty(), OptionalInt.empty()); } return Pair.of(N.findFirstIndex(c, predicateForFirst), N.findLastIndex(c, predicateForLast)); } /** * Find first and last index. * * @param the generic type * @param the element type * @param a the a * @param predicate the predicate * @return the pair * @throws E the e */ public static Pair findFirstAndLastIndex(final T[] a, final Throwables.Predicate predicate) throws E { return findFirstAndLastIndex(a, predicate, predicate); } /** * Find first and last index. * * @param the generic type * @param the element type * @param the generic type * @param a the a * @param predicateForFirst the predicate for first * @param predicateForLast the predicate for last * @return the pair * @throws E the e * @throws E2 the e2 */ public static Pair findFirstAndLastIndex(final T[] a, final Throwables.Predicate predicateForFirst, final Throwables.Predicate predicateForLast) throws E, E2 { if (N.isNullOrEmpty(a)) { return Pair.of(OptionalInt.empty(), OptionalInt.empty()); } return Pair.of(N.findFirstIndex(a, predicateForFirst), N.findLastIndex(a, predicateForLast)); } /** * Find first or last. * * @param the generic type * @param the element type * @param the generic type * @param c the c * @param predicateForFirst the predicate for first * @param predicateForLast the predicate for last * @return the nullable * @throws E the e * @throws E2 the e2 */ public static Nullable findFirstOrLast(final Collection c, final Throwables.Predicate predicateForFirst, final Throwables.Predicate predicateForLast) throws E, E2 { if (N.isNullOrEmpty(c)) { return Nullable. empty(); } final Nullable res = N.findFirst(c, predicateForFirst); return res.isPresent() ? res : N.findLast(c, predicateForLast); } /** * Find first or last. * * @param the generic type * @param the element type * @param the generic type * @param a the a * @param predicateForFirst the predicate for first * @param predicateForLast the predicate for last * @return the nullable * @throws E the e * @throws E2 the e2 */ public static Nullable findFirstOrLast(final T[] a, final Throwables.Predicate predicateForFirst, final Throwables.Predicate predicateForLast) throws E, E2 { if (N.isNullOrEmpty(a)) { return Nullable. empty(); } final Nullable res = N.findFirst(a, predicateForFirst); return res.isPresent() ? res : N.findLast(a, predicateForLast); } /** * Find first and last. * * @param the generic type * @param the element type * @param c the c * @param predicate the predicate * @return the pair * @throws E the e */ public static Pair, Nullable> findFirstAndLast(final Collection c, final Throwables.Predicate predicate) throws E { return findFirstAndLast(c, predicate, predicate); } /** * Find first and last. * * @param the generic type * @param the element type * @param the generic type * @param c the c * @param predicateForFirst the predicate for first * @param predicateForLast the predicate for last * @return the pair * @throws E the e * @throws E2 the e2 */ public static Pair, Nullable> findFirstAndLast(final Collection c, final Throwables.Predicate predicateForFirst, final Throwables.Predicate predicateForLast) throws E, E2 { if (N.isNullOrEmpty(c)) { return Pair.of(Nullable. empty(), Nullable. empty()); } return Pair.of(N.findFirst(c, predicateForFirst), N.findLast(c, predicateForLast)); } /** * Find first and last. * * @param the generic type * @param the element type * @param a the a * @param predicate the predicate * @return the pair * @throws E the e */ public static Pair, Nullable> findFirstAndLast(final T[] a, final Throwables.Predicate predicate) throws E { return findFirstAndLast(a, predicate, predicate); } /** * Find first and last. * * @param the generic type * @param the element type * @param the generic type * @param a the a * @param predicateForFirst the predicate for first * @param predicateForLast the predicate for last * @return the pair * @throws E the e * @throws E2 the e2 */ public static Pair, Nullable> findFirstAndLast(final T[] a, final Throwables.Predicate predicateForFirst, final Throwables.Predicate predicateForLast) throws E, E2 { if (N.isNullOrEmpty(a)) { return Pair.of(Nullable. empty(), Nullable. empty()); } return Pair.of(N.findFirst(a, predicateForFirst), N.findLast(a, predicateForLast)); } // /** // * // * @param // * @param // * @param a // * @param b // * @return // * @see N#crossJoin(Collection, Collection) // * @deprecated replaced by {@code N.crossJoin(Collection, Collection)} // */ // @Deprecated // public static List> crossJoin(final Collection a, final Collection b) { // return crossJoin(a, b, Fn. pair()); // } // // /** // * // * @param // * @param // * @param // * @param // * @param a // * @param b // * @param func // * @return // * @throws E // * @see N#crossJoin(Collection, Collection, com.landawn.abacus.util.Throwables.BiFunction) // * @deprecated replaced by {@code N.crossJoin(Collection, Collection, com.landawn.abacus.util.Try.BiFunction)} // */ // @Deprecated // public static List crossJoin(final Collection a, final Collection b, // final Throwables.BiFunction func) throws E { // N.checkArgNotNull(func, "func"); // // final List result = new ArrayList<>(N.size(a) * N.size(b)); // // if (N.isNullOrEmpty(a) || N.isNullOrEmpty(b)) { // return result; // } // // for (T ae : a) { // for (U be : b) { // result.add(func.apply(ae, be)); // } // } // // 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 the generic type // * @param the generic type // * @param the element type // * @param the generic type // * @param a the a // * @param b the b // * @param leftKeyMapper the left key mapper // * @param rightKeyMapper the right key mapper // * @return the list // * @throws E the e // * @throws E2 the e2 // * @see N#innerJoin(Collection, Collection, com.landawn.abacus.util.Throwables.Function, com.landawn.abacus.util.Throwables.Function) // * @see sql join // * @deprecated replaced by {@code N.innerJoin(Collection, Collection, com.landawn.abacus.util.Try.Function, com.landawn.abacus.util.Try.Function)} // */ // @Deprecated // public static List> innerJoin(final Collection a, final Collection b, // final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper) // throws E, E2 { // final List> result = new ArrayList<>(N.min(9, N.size(a), N.size(b))); // // if (N.isNullOrEmpty(a) || N.isNullOrEmpty(b)) { // return result; // } // // final ListMultimap rightKeyMap = ListMultimap.from(b, rightKeyMapper); // // for (T left : a) { // 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 the generic type // * @param the generic type // * @param the element type // * @param a the a // * @param b the b // * @param predicate the predicate // * @return the list // * @throws E the e // * @see N#innerJoin(Collection, Collection, com.landawn.abacus.util.Throwables.BiPredicate) // * @see sql join // * @deprecated replaced by {@code N.innerJoin(Collection, Collection, com.landawn.abacus.util.Try.BiPredicate)} // */ // @Deprecated // public static List> innerJoin(final Collection a, final Collection b, // final Throwables.BiPredicate predicate) throws E { // final List> result = new ArrayList<>(N.min(9, N.size(a), N.size(b))); // // if (N.isNullOrEmpty(a) || N.isNullOrEmpty(b)) { // return result; // } // // for (T left : a) { // for (U right : b) { // if (predicate.test(left, right)) { // 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 the generic type // * @param the generic type // * @param the element type // * @param the generic type // * @param a the a // * @param b the b // * @param leftKeyMapper the left key mapper // * @param rightKeyMapper the right key mapper // * @return the list // * @throws E the e // * @throws E2 the e2 // * @see N#fullJoin(Collection, Collection, com.landawn.abacus.util.Throwables.Function, com.landawn.abacus.util.Throwables.Function) // * @see sql join // * @deprecated replaced by {@code N.fullJoin(Collection, Collection, com.landawn.abacus.util.Try.Function, com.landawn.abacus.util.Try.Function)} // */ // @Deprecated // public static List> fullJoin(final Collection a, final Collection b, // final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper) // throws E, E2 { // final List> result = new ArrayList<>(N.max(9, N.size(a), N.size(b))); // // if (N.isNullOrEmpty(a)) { // for (T left : a) { // 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 : a) { // 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 the generic type // * @param the generic type // * @param the element type // * @param a the a // * @param b the b // * @param predicate the predicate // * @return the list // * @throws E the e // * @see N#fullJoin(Collection, Collection, com.landawn.abacus.util.Throwables.BiPredicate) // * @see sql join // * @deprecated replaced by {@code N.fullJoin(Collection, Collection, com.landawn.abacus.util.Try.BiPredicate)} // */ // @Deprecated // public static List> fullJoin(final Collection a, final Collection b, // final Throwables.BiPredicate predicate) throws E { // final List> result = new ArrayList<>(N.max(9, N.size(a), N.size(b))); // // if (N.isNullOrEmpty(a)) { // for (T left : a) { // 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 Map joinedRights = new IdentityHashMap<>(); // // for (T left : a) { // boolean joined = false; // // for (U right : b) { // if (predicate.test(left, right)) { // result.add(Pair.of(left, right)); // joinedRights.put(right, right); // joined = true; // } // } // // if (joined == false) { // 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 the generic type // * @param the generic type // * @param the element type // * @param the generic type // * @param a the a // * @param b the b // * @param leftKeyMapper the left key mapper // * @param rightKeyMapper the right key mapper // * @return the list // * @throws E the e // * @throws E2 the e2 // * @see N#leftJoin(Collection, Collection, com.landawn.abacus.util.Throwables.Function, com.landawn.abacus.util.Throwables.Function) // * @see sql join // * @deprecated replaced by {@code N.leftJoin(Collection, Collection, com.landawn.abacus.util.Try.Function, com.landawn.abacus.util.Try.Function)} // */ // @Deprecated // public static List> leftJoin(final Collection a, final Collection b, // final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper) // throws E, E2 { // final List> result = new ArrayList<>(N.size(a)); // // if (N.isNullOrEmpty(a)) { // return result; // } else if (N.isNullOrEmpty(b)) { // for (T left : a) { // result.add(Pair.of(left, (U) null)); // } // } else { // final ListMultimap rightKeyMap = ListMultimap.from(b, rightKeyMapper); // // for (T left : a) { // 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 the generic type // * @param the generic type // * @param the element type // * @param a the a // * @param b the b // * @param predicate the predicate // * @return the list // * @throws E the e // * @see N#leftJoin(Collection, Collection, com.landawn.abacus.util.Throwables.BiPredicate) // * @see sql join // * @deprecated replaced by {@code N.leftJoin(Collection, Collection, com.landawn.abacus.util.Try.BiPredicate)} // */ // @Deprecated // public static List> leftJoin(final Collection a, final Collection b, // final Throwables.BiPredicate predicate) throws E { // final List> result = new ArrayList<>(N.size(a)); // // if (N.isNullOrEmpty(a)) { // return result; // } else if (N.isNullOrEmpty(b)) { // for (T left : a) { // result.add(Pair.of(left, (U) null)); // } // } else { // for (T left : a) { // boolean joined = false; // // for (U right : b) { // if (predicate.test(left, right)) { // result.add(Pair.of(left, right)); // joined = true; // } // } // // if (joined == false) { // 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 the generic type // * @param the generic type // * @param the element type // * @param the generic type // * @param a the a // * @param b the b // * @param leftKeyMapper the left key mapper // * @param rightKeyMapper the right key mapper // * @return the list // * @throws E the e // * @throws E2 the e2 // * @see N#rightJoin(Collection, Collection, com.landawn.abacus.util.Throwables.Function, com.landawn.abacus.util.Throwables.Function) // * @see sql join // * @deprecated replaced by {@code N.rightJoin(Collection, Collection, com.landawn.abacus.util.Try.Function, com.landawn.abacus.util.Try.Function)} // */ // @Deprecated // public static List> rightJoin(final Collection a, final Collection b, // final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper) // throws E, E2 { // final List> result = new ArrayList<>(N.size(b)); // // if (N.isNullOrEmpty(b)) { // return result; // } else if (N.isNullOrEmpty(a)) { // for (U right : b) { // result.add(Pair.of((T) null, right)); // } // } else { // final ListMultimap leftKeyMap = ListMultimap.from(a, 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 the generic type // * @param the generic type // * @param the element type // * @param a the a // * @param b the b // * @param predicate the predicate // * @return the list // * @throws E the e // * @see N#rightJoin(Collection, Collection, com.landawn.abacus.util.Throwables.BiPredicate) // * @see sql join // * @deprecated replaced by {@code N.rightJoin(Collection, Collection, com.landawn.abacus.util.Try.BiPredicate)} // */ // @Deprecated // public static List> rightJoin(final Collection a, final Collection b, // final Throwables.BiPredicate predicate) throws E { // final List> result = new ArrayList<>(N.size(b)); // // if (N.isNullOrEmpty(b)) { // return result; // } else if (N.isNullOrEmpty(a)) { // for (U right : b) { // result.add(Pair.of((T) null, right)); // } // } else { // for (U right : b) { // boolean joined = false; // // for (T left : a) { // if (predicate.test(left, right)) { // result.add(Pair.of(left, right)); // joined = true; // } // } // // if (joined == false) { // result.add(Pair.of((T) null, right)); // } // } // } // // return result; // } @SuppressWarnings("rawtypes") public static boolean padLeft(final List list, final int minLen, final T objToAdd) { N.checkArgNotNegative(minLen, "minLen"); final int size = N.size(list); if (size < minLen) { final int elementCountToAdd = minLen - size; final Object[] a = new Object[elementCountToAdd]; if (objToAdd != null) { N.fill(a, objToAdd); list.addAll(0, (List) Arrays.asList(a)); } return true; } return false; } @SuppressWarnings("rawtypes") public static boolean padRight(final Collection c, final int minLen, final T objToAdd) { N.checkArgNotNegative(minLen, "minLen"); final int size = N.size(c); if (size < minLen) { final int elementCountToAdd = minLen - size; final Object[] a = new Object[elementCountToAdd]; if (objToAdd != null) { N.fill(a, objToAdd); c.addAll((Collection) Arrays.asList(a)); } return true; } return false; } public static abstract class SetView extends ImmutableSet { SetView(final Set set) { super(set); } public > S copyInto(S set) { set.addAll(this); return set; } } /** * Returns an unmodifiable view of the union of two sets. The returned set contains all * elements that are contained in either backing set. Iterating over the returned set iterates * first over all the elements of {@code set1}, then over each element of {@code set2}, in order, * that is not contained in {@code set1}. * *

Results are undefined if {@code set1} and {@code set2} are sets based on different * equivalence relations (as {@link HashSet}, {@link TreeSet}, and the {@link Map#keySet} of an * {@code IdentityHashMap} all are). */ public static SetView union(final Set set1, final Set set2) { // N.checkArgNotNull(set1, "set1"); // N.checkArgNotNull(set2, "set2"); Set tmp = null; if (set1 == null) { tmp = set2 == null ? N. emptySet() : set2; } else if (set2 == null) { tmp = set1; } else { tmp = new AbstractSet() { @Override public ObjIterator iterator() { return new ObjIterator() { private final Iterator iter1 = set1.iterator(); private final Iterator iter2 = set2.iterator(); private final E NONE = (E) N.NULL_MASK; private E next = NONE; private E tmp = null; @Override public boolean hasNext() { if (iter1.hasNext() || next != NONE) { return true; } while (iter2.hasNext()) { next = iter2.next(); if (!set1.contains(next)) { return true; } } next = NONE; return false; } @Override public E next() { if (hasNext() == false) { throw new NoSuchElementException(); } if (iter1.hasNext()) { return iter1.next(); } else { tmp = next; next = NONE; return tmp; } } }; } @Override public boolean contains(Object object) { return set1.contains(object) || set2.contains(object); } @Override public int size() { int size = set1.size(); for (E e : set2) { if (!set1.contains(e)) { size++; } } return size; } @Override public boolean isEmpty() { return set1.isEmpty() && set2.isEmpty(); } }; } return new SetView(tmp) { @Override public > S copyInto(S set) { set.addAll(set1); set.addAll(set2); return set; } }; } /** * Returns an unmodifiable view of the intersection of two sets. The returned set contains * all elements that are contained by both backing sets. The iteration order of the returned set * matches that of {@code set1}. * *

Results are undefined if {@code set1} and {@code set2} are sets based on different * equivalence relations (as {@code HashSet}, {@code TreeSet}, and the keySet of an {@code * IdentityHashMap} all are). * *

Note: The returned view performs slightly better when {@code set1} is the smaller of * the two sets. If you have reason to believe one of your sets will generally be smaller than the * other, pass it first. Unfortunately, since this method sets the generic type of the returned * set based on the type of the first set passed, this could in rare cases force you to make a * cast, for example: * *

{@code
     * Set aFewBadObjects = ...
     * Set manyBadStrings = ...
     *
     * // impossible for a non-String to be in the intersection
     * SuppressWarnings("unchecked")
     * Set badStrings = (Set) Sets.intersection(
     *     aFewBadObjects, manyBadStrings);
     * }
     *
     * 

This is unfortunate, but should come up only very rarely. */ public static SetView intersection(final Set set1, final Set set2) { // N.checkArgNotNull(set1, "set1"); // N.checkArgNotNull(set2, "set2"); Set tmp = null; if (set1 == null || set2 == null) { tmp = N. emptySet(); } else { tmp = new AbstractSet() { @Override public ObjIterator iterator() { return new ObjIterator() { private final Iterator iter1 = set1.iterator(); private final E NONE = (E) N.NULL_MASK; private E next = NONE; private E tmp = null; @Override public boolean hasNext() { if (next != NONE) { return true; } while (iter1.hasNext()) { next = iter1.next(); if (set2.contains(next)) { return true; } } next = NONE; return false; } @Override public E next() { if (hasNext() == false) { throw new NoSuchElementException(); } tmp = next; next = NONE; return tmp; } }; } @Override public boolean contains(Object object) { return set1.contains(object) && set2.contains(object); } @Override public boolean containsAll(Collection collection) { return set1.containsAll(collection) && set2.containsAll(collection); } @Override public int size() { int size = 0; for (E e : set1) { if (set2.contains(e)) { size++; } } return size; } @Override public boolean isEmpty() { return Collections.disjoint(set1, set2); } }; } return new SetView(tmp) { }; } /** * Returns an unmodifiable view of the difference of two sets. The returned set contains * all elements that are contained by {@code set1} and not contained by {@code set2}. {@code set2} * may also contain elements not present in {@code set1}; these are simply ignored. The iteration * order of the returned set matches that of {@code set1}. * *

Results are undefined if {@code set1} and {@code set2} are sets based on different * equivalence relations (as {@code HashSet}, {@code TreeSet}, and the keySet of an {@code * IdentityHashMap} all are). */ public static SetView difference(final Set set1, final Set set2) { // N.checkArgNotNull(set1, "set1"); // N.checkArgNotNull(set2, "set2"); Set tmp = null; if (set2 == null) { tmp = set1 == null ? N. emptySet() : set1; } else { tmp = new AbstractSet() { @Override public ObjIterator iterator() { return new ObjIterator() { private final Iterator iter1 = set1.iterator(); private final E NONE = (E) N.NULL_MASK; private E next = NONE; private E tmp = null; @Override public boolean hasNext() { if (next != NONE) { return true; } while (iter1.hasNext()) { next = iter1.next(); if (!set2.contains(next)) { return true; } } next = NONE; return false; } @Override public E next() { if (hasNext() == false) { throw new NoSuchElementException(); } tmp = next; next = NONE; return tmp; } }; } @Override public boolean contains(Object object) { return set1.contains(object) && !set2.contains(object); } @Override public int size() { int size = 0; for (E e : set1) { if (!set2.contains(e)) { size++; } } return size; } @Override public boolean isEmpty() { return set2.containsAll(set1); } }; } return new SetView(tmp) { }; } /** * Returns an unmodifiable view of the symmetric difference of two sets. The returned set * contains all elements that are contained in either {@code set1} or {@code set2} but not in * both. The iteration order of the returned set is undefined. * *

Results are undefined if {@code set1} and {@code set2} are sets based on different * equivalence relations (as {@code HashSet}, {@code TreeSet}, and the keySet of an {@code * IdentityHashMap} all are). * * @since 3.0 */ public static SetView symmetricDifference(final Set set1, final Set set2) { // N.checkArgNotNull(set1, "set1"); // N.checkArgNotNull(set2, "set2"); Set tmp = null; if (set1 == null) { tmp = set2 == null ? N. emptySet() : set2; } else if (set2 == null) { tmp = set1; } else { tmp = new AbstractSet() { @Override public ObjIterator iterator() { return new ObjIterator() { private final Iterator iter1 = set1.iterator(); private final Iterator iter2 = set2.iterator(); private final E NONE = (E) N.NULL_MASK; private E next = NONE; private E tmp = null; @Override public boolean hasNext() { if (next != NONE) { return true; } while (iter1.hasNext()) { next = iter1.next(); if (!set2.contains(next)) { return true; } } while (iter2.hasNext()) { next = iter2.next(); if (!set1.contains(next)) { return true; } } next = NONE; return false; } @Override public E next() { if (hasNext() == false) { throw new NoSuchElementException(); } tmp = next; next = NONE; return tmp; } }; } @Override public boolean contains(Object object) { return set1.contains(object) ^ set2.contains(object); } @Override public int size() { int size = 0; for (E e : set1) { if (!set2.contains(e)) { size++; } } for (E e : set2) { if (!set1.contains(e)) { size++; } } return size; } @Override public boolean isEmpty() { return set1.equals(set2); } }; } return new SetView(tmp) { }; } /** * The Class Slice. * * @param the generic type */ static final class Slice extends ImmutableCollection { /** The from index. */ private final int fromIndex; /** The to index. */ private final int toIndex; /** * Instantiates a new sub collection. * * @param a the a * @param fromIndex the from index * @param toIndex the to index */ Slice(final T[] a, final int fromIndex, final int toIndex) { this(Array.asList(a), fromIndex, toIndex); } /** * Instantiates a new sub collection. * * @param c the c * @param fromIndex the from index * @param toIndex the to index */ Slice(final Collection c, final int fromIndex, final int toIndex) { super(c); this.fromIndex = fromIndex; this.toIndex = toIndex; } /** * Contains. * * @param o the o * @return */ @Override public boolean contains(Object o) { final Iterator iter = this.iterator(); while (iter.hasNext()) { if (N.equals(iter.next(), o)) { return true; } } return false; } /** * Contains all. * * @param c the c * @return */ @Override public boolean containsAll(final Collection c) { for (Object e : c) { if (contains(e) == false) { return false; } } return true; } /** * Checks if is empty. * * @return true, if is empty */ @Override public boolean isEmpty() { return size() == 0; } /** * Size. * * @return the int */ @Override public int size() { return toIndex - fromIndex; } /** * Iterator. * * @return the iterator */ @Override public ObjIterator iterator() { if (coll == null || fromIndex == toIndex) { return ObjIterator. empty(); } final Iterator iter = coll.iterator(); if (fromIndex == 0 && toIndex == coll.size()) { return ObjIterator.of(iter); } else if (fromIndex == 0) { return Iterators.limit(iter, toIndex - fromIndex); } else if (toIndex == coll.size()) { return Iterators.skip(iter, fromIndex); } else { return Iterators.skipAndLimit(iter, fromIndex, toIndex - fromIndex); } } /** * To array. * * @return the object[] */ @Override public Object[] toArray() { final Iterator iter = this.iterator(); final Object[] a = new Object[size()]; for (int i = 0, len = a.length; i < len; i++) { a[i] = iter.next(); } return a; } /** * To array. * * @param the generic type * @param a the a * @return the a[] */ @Override public A[] toArray(A[] a) { if (a.length < size()) { a = N.copyOf(a, size()); } final Iterator iter = this.iterator(); for (int i = 0, len = a.length; i < len; i++) { a[i] = (A) iter.next(); } return a; } } }