Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.landawn.abacus.util.N Maven / Gradle / Ivy
Go to download
A general programming library in Java/Android. It's easy to learn and simple to use with concise and powerful APIs.
/*
* Copyright (c) 2015, 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.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.RandomAccess;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.DoublePredicate;
import java.util.function.DoubleToIntFunction;
import java.util.function.DoubleToLongFunction;
import java.util.function.DoubleUnaryOperator;
import java.util.function.Function;
import java.util.function.IntBinaryOperator;
import java.util.function.IntFunction;
import java.util.function.IntPredicate;
import java.util.function.IntToDoubleFunction;
import java.util.function.IntToLongFunction;
import java.util.function.IntUnaryOperator;
import java.util.function.LongPredicate;
import java.util.function.LongToDoubleFunction;
import java.util.function.LongToIntFunction;
import java.util.function.LongUnaryOperator;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.function.UnaryOperator;
import java.util.stream.Collector;
import com.landawn.abacus.annotation.Beta;
import com.landawn.abacus.annotation.MayReturnNull;
import com.landawn.abacus.annotation.NotNull;
import com.landawn.abacus.parser.DeserializationConfig;
import com.landawn.abacus.parser.JSONDeserializationConfig;
import com.landawn.abacus.parser.JSONDeserializationConfig.JDC;
import com.landawn.abacus.parser.JSONSerializationConfig;
import com.landawn.abacus.parser.XMLDeserializationConfig;
import com.landawn.abacus.parser.XMLDeserializationConfig.XDC;
import com.landawn.abacus.parser.XMLSerializationConfig;
import com.landawn.abacus.type.Type;
import com.landawn.abacus.util.Fn.Factory;
import com.landawn.abacus.util.Fn.Fnn;
import com.landawn.abacus.util.Fn.IntFunctions;
import com.landawn.abacus.util.Fn.Suppliers;
import com.landawn.abacus.util.Iterables.Slice;
import com.landawn.abacus.util.Tuple.Tuple2;
import com.landawn.abacus.util.Tuple.Tuple3;
import com.landawn.abacus.util.Tuple.Tuple4;
import com.landawn.abacus.util.Tuple.Tuple5;
import com.landawn.abacus.util.u.Nullable;
import com.landawn.abacus.util.function.BooleanPredicate;
import com.landawn.abacus.util.function.BooleanUnaryOperator;
import com.landawn.abacus.util.function.BytePredicate;
import com.landawn.abacus.util.function.ByteUnaryOperator;
import com.landawn.abacus.util.function.CharPredicate;
import com.landawn.abacus.util.function.CharUnaryOperator;
import com.landawn.abacus.util.function.FloatPredicate;
import com.landawn.abacus.util.function.FloatUnaryOperator;
import com.landawn.abacus.util.function.IntBiFunction;
import com.landawn.abacus.util.function.IntToBooleanFunction;
import com.landawn.abacus.util.function.IntToByteFunction;
import com.landawn.abacus.util.function.IntToCharFunction;
import com.landawn.abacus.util.function.IntToFloatFunction;
import com.landawn.abacus.util.function.IntToShortFunction;
import com.landawn.abacus.util.function.ShortPredicate;
import com.landawn.abacus.util.function.ShortUnaryOperator;
import com.landawn.abacus.util.function.ToBooleanFunction;
import com.landawn.abacus.util.function.ToByteFunction;
import com.landawn.abacus.util.function.ToCharFunction;
import com.landawn.abacus.util.function.ToFloatFunction;
import com.landawn.abacus.util.function.ToShortFunction;
import com.landawn.abacus.util.function.TriFunction;
import com.landawn.abacus.util.stream.IntStream;
import com.landawn.abacus.util.stream.Stream;
/**
*
* 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.
*
* Class {@code N} is a general java utility class. It provides the most daily used operations for Object/primitive types/String/Array/Collection/Map/Bean...:
*
*
*
* When to throw exception? It's designed to avoid throwing any unnecessary
* exception if the contract defined by method is not broken. for example, if
* user tries to reverse a {@code null} or empty String. the input String will be
* returned. But exception will be thrown if try to add element to a {@code null} Object array or collection.
*
*
* An empty String/Array/Collection/Map/Iterator/Iterable/InputStream/Reader will always be a preferred choice than a {@code null} for the return value of a method.
*
* There are only {@code fromIndex/startIndex} and {toIndex/endIndex} parameters in the methods defined in class {@code CommonUtil/N}, no {@code offset/count} parameters.
*
*
* @see com.landawn.abacus.util.Comparators
* @see com.landawn.abacus.util.Fn
* @see com.landawn.abacus.util.Fn.Fnn
* @see com.landawn.abacus.util.Array
* @see com.landawn.abacus.util.CommonUtil
* @see com.landawn.abacus.util.Iterables
* @see com.landawn.abacus.util.Iterators
* @see com.landawn.abacus.util.Index
* @see com.landawn.abacus.util.Median
* @see com.landawn.abacus.util.Maps
* @see com.landawn.abacus.util.Strings
* @see com.landawn.abacus.util.Numbers
* @see java.lang.reflect.Array
* @see java.util.Arrays
* @see java.util.Collections
*
* @version $Revision: 0.8 $ 07/03/10
*
*/
@SuppressWarnings({ "java:S1192", "java:S6539" })
public final class N extends CommonUtil { // public final class N extends π implements ℕ, ℂ, ℚ, ℝ, ℤ { // Error while storing the mojo status in Maven
static final AsyncExecutor ASYNC_EXECUTOR = new AsyncExecutor(//
max(64, InternalUtil.CPU_CORES * 8), // coreThreadPoolSize
max(128, InternalUtil.CPU_CORES * 16), // maxThreadPoolSize
180L, TimeUnit.SECONDS);
static final ScheduledExecutorService SCHEDULED_EXECUTOR;
static {
final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(Math.max(64, InternalUtil.CPU_CORES));
// executor.setKeepAliveTime(180, TimeUnit.SECONDS);
// executor.allowCoreThreadTimeOut(true);
// executor.setRemoveOnCancelPolicy(true);
SCHEDULED_EXECUTOR = MoreExecutors.getExitingScheduledExecutorService(executor);
}
private static final float LOAD_FACTOR_FOR_FLAT_MAP = 1.75f;
private static final int LOAD_FACTOR_FOR_TWO_FLAT_MAP = 2;
private N() {
// Utility class.
}
/**
* Counts the occurrences of a specific boolean value in a boolean array.
*
* @param a The boolean array to be checked for the presence of the valueToFind.
* @param valueToFind The boolean value to be checked for its occurrences in the array a.
* @return The number of occurrences of valueToFind in array a. Returns 0 if the array is {@code null} or empty.
*/
public static int occurrencesOf(final boolean[] a, final boolean valueToFind) {
if (isEmpty(a)) {
return 0;
}
int occurrences = 0;
for (final boolean element : a) {
if (element == valueToFind) {
occurrences++;
}
}
return occurrences;
}
/**
* Counts the occurrences of a specific char value in a char array.
*
* @param a The char array to be checked for the presence of the valueToFind.
* @param valueToFind The char value to be checked for its occurrences in the array a.
* @return The number of occurrences of valueToFind in array a. Returns 0 if the array is {@code null} or empty.
*/
public static int occurrencesOf(final char[] a, final char valueToFind) {
if (isEmpty(a)) {
return 0;
}
int occurrences = 0;
for (final char element : a) {
if (element == valueToFind) {
occurrences++;
}
}
return occurrences;
}
/**
* Counts the occurrences of a specific byte value in a byte array.
*
* @param a The byte array to be checked for the presence of the valueToFind.
* @param valueToFind The byte value to be checked for its occurrences in the array a.
* @return The number of occurrences of valueToFind in array a. Returns 0 if the array is {@code null} or empty.
*/
public static int occurrencesOf(final byte[] a, final byte valueToFind) {
if (isEmpty(a)) {
return 0;
}
int occurrences = 0;
for (final byte element : a) {
if (element == valueToFind) {
occurrences++;
}
}
return occurrences;
}
/**
* Counts the occurrences of a specific short value in a short array.
*
* @param a The short array to be checked for the presence of the valueToFind.
* @param valueToFind The short value to be checked for its occurrences in the array a.
* @return The number of occurrences of valueToFind in array a. Returns 0 if the array is {@code null} or empty.
*/
public static int occurrencesOf(final short[] a, final short valueToFind) {
if (isEmpty(a)) {
return 0;
}
int occurrences = 0;
for (final short element : a) {
if (element == valueToFind) {
occurrences++;
}
}
return occurrences;
}
/**
* Counts the occurrences of a specific int value in a int array.
*
* @param a The int array to be checked for the presence of the valueToFind.
* @param valueToFind The int value to be checked for its occurrences in the array a.
* @return The number of occurrences of valueToFind in array a. Returns 0 if the array is {@code null} or empty.
*/
public static int occurrencesOf(final int[] a, final int valueToFind) {
if (isEmpty(a)) {
return 0;
}
int occurrences = 0;
for (final int element : a) {
if (element == valueToFind) {
occurrences++;
}
}
return occurrences;
}
/**
* Counts the occurrences of a specific long value in a long array.
*
* @param a The long array to be checked for the presence of the valueToFind.
* @param valueToFind The long value to be checked for its occurrences in the array a.
* @return The number of occurrences of valueToFind in array a. Returns 0 if the array is {@code null} or empty.
*/
public static int occurrencesOf(final long[] a, final long valueToFind) {
if (isEmpty(a)) {
return 0;
}
int occurrences = 0;
for (final long element : a) {
if (element == valueToFind) {
occurrences++;
}
}
return occurrences;
}
/**
* Counts the occurrences of a specific float value in a float array.
*
* @param a The float array to be checked for the presence of the valueToFind.
* @param valueToFind The float value to be checked for its occurrences in the array a.
* @return The number of occurrences of valueToFind in array a. Returns 0 if the array is {@code null} or empty.
*/
public static int occurrencesOf(final float[] a, final float valueToFind) {
if (isEmpty(a)) {
return 0;
}
int occurrences = 0;
for (final float element : a) {
if (Float.compare(element, valueToFind) == 0) {
occurrences++;
}
}
return occurrences;
}
/**
* Counts the occurrences of a specific double value in a double array.
*
* @param a The double array to be checked for the presence of the valueToFind.
* @param valueToFind The double value to be checked for its occurrences in the array a.
* @return The number of occurrences of valueToFind in array a. Returns 0 if the array is {@code null} or empty.
*/
public static int occurrencesOf(final double[] a, final double valueToFind) {
if (isEmpty(a)) {
return 0;
}
int occurrences = 0;
for (final double element : a) {
if (Double.compare(element, valueToFind) == 0) {
occurrences++;
}
}
return occurrences;
}
/**
* Counts the occurrences of a specific Object value in an Object array.
*
* @param a The Object array to be checked for the presence of the valueToFind.
* @param valueToFind The Object value to be checked for its occurrences in the array a.
* @return The number of occurrences of valueToFind in array a. Returns 0 if the array is {@code null} or empty.
*/
public static int occurrencesOf(final Object[] a, final Object valueToFind) {
if (isEmpty(a)) {
return 0;
}
int occurrences = 0;
if (valueToFind == null) {
for (final Object element : a) {
if (element == null) {
occurrences++;
}
}
} else {
for (final Object element : a) {
if (valueToFind.equals(element)) {
occurrences++;
}
}
}
return occurrences;
}
/**
* Counts the occurrences of a specific Object value in an {@code Iterable}.
*
* @param c The {@code Iterable} to be checked for the presence of the valueToFind.
* @param valueToFind The Object value to be checked for its occurrences in the {@code Iterable} c .
* @return The number of occurrences of valueToFind in {@code Iterable} c . Returns 0 if the {@code Iterable} is {@code null}.
*/
public static int occurrencesOf(final Iterable> c, final Object valueToFind) {
if (isEmptyCollection(c)) {
return 0;
}
long occurrences = 0;
if (valueToFind == null) {
for (final Object e : c) {
if (e == null) {
occurrences++;
}
}
} else {
for (final Object e : c) {
if (equals(e, valueToFind)) {
occurrences++;
}
}
}
return Numbers.toIntExact(occurrences);
}
/**
* Counts the occurrences of a specific Object value in an {@code Iterator}.
*
* @param iter The {@code Iterator} to be checked for the presence of the valueToFind.
* @param valueToFind The Object value to be checked for its occurrences in the Iterator iter .
* @return The number of occurrences of valueToFind in Iterator iter . Returns 0 if the Iterator is {@code null}.
* @throws ArithmeticException if the number of occurrences exceeds Integer.MAX_VALUE.
* @see Iterators#occurrencesOf(Iterator, Object)
*/
public static int occurrencesOf(final Iterator> iter, final Object valueToFind) throws ArithmeticException {
return Numbers.toIntExact(Iterators.occurrencesOf(iter, valueToFind));
}
/**
* Counts the occurrences of a specific character in a String.
*
* @param str The String to be checked for the presence of the valueToFind.
* @param valueToFind The character to be checked for its occurrences in the String str .
* @return The number of occurrences of valueToFind in String str . Returns 0 if the String is {@code null} or empty.
* @see Strings#countMatches(String, char)
*/
public static int occurrencesOf(final String str, final char valueToFind) {
return Strings.countMatches(str, valueToFind);
}
/**
* Counts the occurrences of a specific String value in another String.
*
* @param str The String to be checked for the presence of the valueToFind.
* @param valueToFind The String value to be checked for its occurrences in the String str .
* @return The number of occurrences of valueToFind in String str . Returns 0 if the String is {@code null} or empty.
* @see Strings#countMatches(String, String)
*/
public static int occurrencesOf(final String str, final String valueToFind) {
return Strings.countMatches(str, valueToFind);
}
/**
* Returns a map with the occurrences of each element in the given array.
* The map's keys are the distinct elements in the array, and their corresponding values are the number of occurrences of each element.
* If the input array is {@code null} or empty, an empty map is returned.
*
* @param the type of elements in the input array
* @param a the array to count occurrences from
* @return a Map containing the elements of the array as keys and their occurrences as values
*/
public static Map occurrencesMap(final T[] a) {
return occurrencesMap(a, Suppliers.ofMap());
}
/**
* Returns a map with the occurrences of each element in the given array.
* The map's keys are the distinct elements in the array, and their corresponding values are the number of occurrences of each element.
* If the input array is {@code null} or empty, a map provided by the supplied map supplier is returned.
*
* @param the type of elements in the input array
* @param a the array to count occurrences from
* @param mapSupplier the supplier of the map to be used for collecting occurrences
* @return a Map containing the elements of the array as keys and their occurrences as values
*/
public static Map occurrencesMap(final T[] a, final Supplier> mapSupplier) {
if (isEmpty(a)) {
return mapSupplier.get();
}
final Map map = mapSupplier.get();
for (final T e : a) {
map.merge(e, 1, Integer::sum);
}
return map;
}
/**
* Returns a map with the occurrences of each element in the given iterable collection.
* The map's keys are the distinct elements in the collection, and their corresponding values are the number of occurrences of each element.
* If the input collection is {@code null}, an empty map is returned.
*
* @param the type of elements in the input collection
* @param c the collection to count occurrences from
* @return a Map containing the elements of the collection as keys and their occurrences as values
*/
public static Map occurrencesMap(final Iterable extends T> c) {
return occurrencesMap(c, Suppliers.ofMap());
}
/**
* Returns a map with the occurrences of each element in the given iterable collection.
* The map's keys are the distinct elements in the collection, and their corresponding values are the number of occurrences of each element.
* If the input collection is {@code null}, a map provided by the supplied map supplier is returned.
*
* @param the type of elements in the input collection
* @param c the collection to count occurrences from
* @param mapSupplier the supplier of the map to be used for collecting occurrences
* @return a Map containing the elements of the collection as keys and their occurrences as values
*/
public static Map occurrencesMap(final Iterable extends T> c, final Supplier> mapSupplier) {
if (isEmptyCollection(c)) {
return mapSupplier.get();
}
final Multiset multiset = new Multiset<>();
for (final T e : c) {
multiset.add(e, 1);
}
final Map map = mapSupplier.get();
for (final T e : multiset) {
map.put(e, multiset.getCount(e));
}
return map;
}
/**
* Returns a map with the occurrences of each element in the given iterator.
* The map's keys are the distinct elements in the iterator, and their corresponding values are the number of occurrences of each element.
* If the input iterator is {@code null} or empty, an empty map is returned.
*
* @param the type of elements in the input iterator
* @param iter the iterator to count occurrences from
* @return a Map containing the elements of the iterator as keys and their occurrences as values
*/
public static Map occurrencesMap(final Iterator extends T> iter) {
return occurrencesMap(iter, Suppliers.ofMap());
}
/**
* Returns a map with the occurrences of each element in the given iterator.
* The map's keys are the distinct elements in the iterator, and their corresponding values are the number of occurrences of each element.
* If the input iterator is {@code null} or empty, a map provided by the supplied map supplier is returned.
*
* @param the type of elements in the input iterator
* @param iter the iterator to count occurrences from
* @param mapSupplier the supplier of the map to be used for collecting occurrences
* @return a Map containing the elements of the iterator as keys and their occurrences as values
*/
public static Map occurrencesMap(final Iterator extends T> iter, final Supplier> mapSupplier) {
if (iter == null) {
return mapSupplier.get();
}
final Multiset multiset = new Multiset<>();
while (iter.hasNext()) {
multiset.add(iter.next(), 1);
}
final Map map = mapSupplier.get();
for (final T e : multiset) {
map.put(e, Numbers.toIntExact(multiset.getCount(e)));
}
return map;
}
// /**
// *
// * @param
// * @param a
// * @return
// * @see Multiset#of(Object[])
// */
// @Beta
// public static Multiset occurrences(final T[] a) {
// return Multiset.of(a);
// }
//
// /**
// *
// * @param
// * @param c
// * @return
// * @see Multiset#of(Iterable)
// */
// @Beta
// public static Multiset occurrences(final Iterable extends T> c) {
// if (isEmptyCollection(c)) {
// return newMultiset();
// }
//
// if (c instanceof Collection) {
// return Multiset.create((Collection) c);
// }
//
// return occurrences(c.iterator());
// }
//
// /**
// *
// * @param
// * @param iter
// * @return
// * @see Multiset#of(Iterator)
// */
// @Beta
// public static Multiset occurrences(final Iterator extends T> iter) {
// return Multiset.create(iter);
// }
/**
* Checks if the specified array contains the specified value.
*
* @param a The array to be checked for the presence of the value.
* @param valueToFind The value to be checked for its presence in the array.
* @return {@code true} if the array contains the specified value, {@code false} if a is {@code null} or empty or {@code valueToFind} is not found.
*/
public static boolean contains(final boolean[] a, final boolean valueToFind) {
return indexOf(a, valueToFind) != INDEX_NOT_FOUND;
}
/**
* Checks if the specified array contains the specified value.
*
* @param a The array to be checked for the presence of the value.
* @param valueToFind The value to be checked for its presence in the array.
* @return {@code true} if the array contains the specified value, {@code false} if a is {@code null} or empty or {@code valueToFind} is not found.
*/
public static boolean contains(final char[] a, final char valueToFind) {
return indexOf(a, valueToFind) != INDEX_NOT_FOUND;
}
/**
* Checks if the specified array contains the specified value.
*
* @param a The array to be checked for the presence of the value.
* @param valueToFind The value to be checked for its presence in the array.
* @return {@code true} if the array contains the specified value, {@code false} if a is {@code null} or empty or {@code valueToFind} is not found.
*/
public static boolean contains(final byte[] a, final byte valueToFind) {
return indexOf(a, valueToFind) != INDEX_NOT_FOUND;
}
/**
* Checks if the specified array contains the specified value.
*
* @param a The array to be checked for the presence of the value.
* @param valueToFind The value to be checked for its presence in the array.
* @return {@code true} if the array contains the specified value, {@code false} if a is {@code null} or empty or {@code valueToFind} is not found.
*/
public static boolean contains(final short[] a, final short valueToFind) {
return indexOf(a, valueToFind) != INDEX_NOT_FOUND;
}
/**
* Checks if the specified array contains the specified value.
*
* @param a The array to be checked for the presence of the value.
* @param valueToFind The value to be checked for its presence in the array.
* @return {@code true} if the array contains the specified value, {@code false} if a is {@code null} or empty or {@code valueToFind} is not found.
*/
public static boolean contains(final int[] a, final int valueToFind) {
return indexOf(a, valueToFind) != INDEX_NOT_FOUND;
}
/**
* Checks if the specified array contains the specified value.
*
* @param a The array to be checked for the presence of the value.
* @param valueToFind The value to be checked for its presence in the array.
* @return {@code true} if the array contains the specified value, {@code false} if a is {@code null} or empty or {@code valueToFind} is not found.
*/
public static boolean contains(final long[] a, final long valueToFind) {
return indexOf(a, valueToFind) != INDEX_NOT_FOUND;
}
/**
* Checks if the specified array contains the specified value.
*
* @param a The array to be checked for the presence of the value.
* @param valueToFind The value to be checked for its presence in the array.
* @return {@code true} if the array contains the specified value, {@code false} if a is {@code null} or empty or {@code valueToFind} is not found.
*/
public static boolean contains(final float[] a, final float valueToFind) {
return indexOf(a, valueToFind) != INDEX_NOT_FOUND;
}
/**
* Checks if the specified array contains the specified value.
*
* @param a The array to be checked for the presence of the value.
* @param valueToFind The value to be checked for its presence in the array.
* @return {@code true} if the array contains the specified value, {@code false} if a is {@code null} or empty or {@code valueToFind} is not found.
*/
public static boolean contains(final double[] a, final double valueToFind) {
return indexOf(a, valueToFind) != INDEX_NOT_FOUND;
}
/**
* Checks if the specified array contains the specified value.
*
* @param a The array to be checked for the presence of the value.
* @param valueToFind The value to be checked for its presence in the array.
* @return {@code true} if the array contains the specified value, {@code false} if a is {@code null} or empty or {@code valueToFind} is not found.
*/
public static boolean contains(final Object[] a, final Object valueToFind) {
return indexOf(a, valueToFind) != INDEX_NOT_FOUND;
}
/**
* Checks if the specified Collection contains the specified value.
*
* @param c The Collection to be checked for the presence of the Collection.
* @param valueToFind The value to be checked for its presence in the array.
* @return {@code true} if the array contains the specified value, {@code false} if {@code valueToFind} is not found or c is {@code null} or empty.
*/
public static boolean contains(final Collection> c, final Object valueToFind) {
if (isEmpty(c)) {
return false;
}
return c.contains(valueToFind);
}
/**
* Checks if the specified {@code Iterable} contains the specified value.
*
* @param c The {@code Iterable} to be checked for the presence of the value.
* @param valueToFind The value to be checked for its presence in the {@code Iterable}.
* @return {@code true} if the array contains the specified value, {@code false} if {@code valueToFind} is not found or c is {@code null} or empty.
*/
public static boolean contains(final Iterable> c, final Object valueToFind) {
if (isEmptyCollection(c)) {
return false;
}
for (final Object e : c) {
if (equals(e, valueToFind)) {
return true;
}
}
return false;
}
/**
* Checks if the specified Iterator contains the specified value.
*
* @param iter The {@code Iterator} to be checked for the presence of the value.
* @param valueToFind The value to be checked for its presence in the Iterator.
* @return {@code true} if the array contains the specified value, {@code false} if {@code valueToFind} is not found or c is {@code null} or empty.
*/
public static boolean contains(final Iterator> iter, final Object valueToFind) {
if (iter == null) {
return false;
}
while (iter.hasNext()) {
if (equals(iter.next(), valueToFind)) {
return true;
}
}
return false;
}
/**
* Checks if the given {@code Collection} contains all the elements in the specified {@code valuesToFind} Collection.
*
* @param c The {@code Collection} to be checked for the presence of the elements in valuesToFind.
* @param valuesToFind The values to be checked for their presence in the given {@code Collection}.
* @return {@code true} if the given {@code Collection} contains all the elements in {@code valuesToFind} or {@code valuesToFind} is {@code null} or empty, {@code false} otherwise if any element in {@code valuesToFind} is not found in the given {@code Collection} or the given {@code Collection} is {@code null} or empty.
*/
public static boolean containsAll(final Collection> c, final Collection> valuesToFind) {
if (isEmpty(valuesToFind)) {
return true;
} else if (isEmpty(c)) {
return false;
}
//noinspection SuspiciousMethodCalls
return c.containsAll(valuesToFind);
}
/**
* Checks if the given {@code Collection} contains all the elements in the specified {@code valuesToFind} array.
*
* @param c The {@code Collection} to be checked for the presence of the elements in valuesToFind.
* @param valuesToFind The values to be checked for their presence in the given {@code Collection}.
* @return {@code true} if the given {@code Collection} contains all the elements in {@code valuesToFind} or {@code valuesToFind} is {@code null} or empty, {@code false} otherwise if any element in {@code valuesToFind} is not found in the given {@code Collection} or the given {@code Collection} is {@code null} or empty.
*/
@SafeVarargs
public static boolean containsAll(final Collection> c, final Object... valuesToFind) {
if (isEmpty(valuesToFind)) {
return true;
} else if (isEmpty(c)) {
return false;
}
//noinspection SuspiciousMethodCalls
return c.containsAll(Array.asList(valuesToFind));
}
/**
* Checks if the given {@code Iterable} contains all the elements in the specified {@code valuesToFind} Collection.
*
* @param c The {@code Iterable} to be checked for the presence of the elements in valuesToFind.
* @param valuesToFind The values to be checked for their presence in the given {@code Iterable}.
* @return {@code true} if the given {@code Iterable} contains all the elements in {@code valuesToFind} or {@code valuesToFind} is {@code null} or empty, {@code false} otherwise if any element in {@code valuesToFind} is not found is not found in the given {@code Iterable} or the given {@code Iterable} is {@code null} or empty.
*/
public static boolean containsAll(final Iterable> c, final Collection> valuesToFind) {
if (isEmpty(valuesToFind)) {
return true;
} else if (isEmptyCollection(c)) {
return false;
}
final Set> set = new HashSet<>(valuesToFind);
for (final Object e : c) {
if (set.remove(e) && (set.size() == 0)) {
return true;
}
}
return false;
}
/**
* Checks if the given {@code Iterator} contains all the elements in the specified {@code valuesToFind} Collection.
*
* @param iter The {@code Iterator} to be checked for the presence of the elements in valuesToFind.
* @param valuesToFind The values to be checked for their presence in the given {@code Iterator}.
* @return {@code true} if the given {@code Iterator} contains all the elements in {@code valuesToFind} or {@code valuesToFind} is {@code null} or empty, {@code false} otherwise if any element in {@code valuesToFind} is not found in the given {@code Iterator} or the given {@code Iterator} is {@code null} or empty.
*/
public static boolean containsAll(final Iterator> iter, final Collection> valuesToFind) {
if (isEmpty(valuesToFind)) {
return true;
} else if (iter == null) {
return false;
}
final Set> set = new HashSet<>(valuesToFind);
while (iter.hasNext()) {
if (set.remove(iter.next()) && (set.size() == 0)) {
return true;
}
}
return false;
}
/**
* Checks if the given {@code Collection} contains any elements from the specified {@code valuesToFind} Collection.
*
* @param c The {@code Collection} to be checked for the presence of any elements in valuesToFind.
* @param valuesToFind The values to be checked for their presence in the given {@code Collection}.
* @return {@code true} if the given {@code Collection} contains any elements in {@code valuesToFind}, {@code false} otherwise if doesn't or if the given {@code Collection} is {@code null} or empty, or if the specified {@code valuesToFind} is {@code null} or empty.
*/
public static boolean containsAny(final Collection> c, final Collection> valuesToFind) {
if (isEmpty(c) || isEmpty(valuesToFind)) {
return false;
}
return !disjoint(c, valuesToFind);
}
/**
* Checks if the given {@code Collection} contains any elements from the specified {@code valuesToFind} array.
*
* @param c The {@code Collection} to be checked for the presence of any elements in valuesToFind.
* @param valuesToFind The values to be checked for their presence in the {given {@code Collection}.
* @return {@code true} if the given {@code Collection} contains any elements in {@code valuesToFind}, {@code false} otherwise if doesn't or if the given {@code Collection} is {@code null} or empty, or if the specified {@code valuesToFind} is {@code null} or empty.
*/
@SafeVarargs
public static boolean containsAny(final Collection> c, final Object... valuesToFind) {
if (isEmpty(c) || isEmpty(valuesToFind)) {
return false;
}
return !disjoint(c, Array.asList(valuesToFind));
}
/**
* Checks if the given {@code Iterable} contains any elements from the specified {@code valuesToFind} Set.
*
* @param c The {@code Iterable} to be checked for the presence of any elements in valuesToFind.
* @param valuesToFind The values to be checked for their presence in the given {@code Iterable}.
* @return {@code true} if the given {@code Iterable} contains any elements in {@code valuesToFind}, {@code false} otherwise if doesn't or if the given {@code Iterable} is {@code null} or empty, or if the specified {@code valuesToFind} is {@code null} or empty.
*/
public static boolean containsAny(final Iterable> c, final Set> valuesToFind) {
if (isEmptyCollection(c) || isEmpty(valuesToFind)) {
return false;
}
for (final Object e : c) {
if (valuesToFind.contains(e)) {
return true;
}
}
return false;
}
/**
* Checks if the given {@code Iterator} contains any elements from the specified {@code valuesToFind} Set.
*
* @param iter The {@code Iterator} to be checked for the presence of any elements in valuesToFind.
* @param valuesToFind The values to be checked for their presence in the given {@code Iterator}.
* @return {@code true} if the given {@code Iterator} contains any elements in {@code valuesToFind}, {@code false} otherwise if doesn't or if the given {@code Iterator} is {@code null} or empty, or if the specified {@code valuesToFind} is {@code null} or empty.
*/
public static boolean containsAny(final Iterator> iter, final Set> valuesToFind) {
if (iter == null || isEmpty(valuesToFind)) {
return false;
}
while (iter.hasNext()) {
if (valuesToFind.contains(iter.next())) {
return true;
}
}
return false;
}
/**
* Checks if the given {@code Collection} doesn't contain any elements from the specified {@code valuesToFind} Collection.
*
* @param c The {@code Collection} to be checked for the presence of any elements in valuesToFind.
* @param valuesToFind The values to be checked for their presence in the given {@code Collection}.
* @return {@code true} if the given {@code Collection} doesn't contain any elements in {@code valuesToFind} or if the given {@code Collection} is {@code null} or empty, or if the specified {@code valuesToFind} is {@code null} or empty, {@code false} otherwise
*/
public static boolean containsNone(final Collection> c, final Collection> valuesToFind) {
if (isEmpty(c) || isEmpty(valuesToFind)) {
return true;
}
return !containsAny(c, valuesToFind);
}
/**
* Checks if the specified given {@code Collection} doesn't contain any elements from the specified {@code valuesToFind} array.
*
* @param c The {@code Collection} to be checked for the presence of any elements in valuesToFind.
* @param valuesToFind The values to be checked for their presence in the given {@code Collection}.
* @return {@code true} if the given {@code Collection} doesn't contain any elements in {@code valuesToFind} or if the given {@code Collection} is {@code null} or empty, or if the specified {@code valuesToFind} is {@code null} or empty, {@code false} otherwise
*/
@SafeVarargs
public static boolean containsNone(final Collection> c, final Object... valuesToFind) {
if (isEmpty(c) || isEmpty(valuesToFind)) {
return true;
}
return !containsAny(c, valuesToFind);
}
/**
* Checks if the given {@code Iterable} doesn't contain any elements from the specified {@code valuesToFind} Set.
*
* @param c The {@code Iterable} to be checked for the presence of any elements in valuesToFind.
* @param valuesToFind The values to be checked for their presence in given {@code Iterable}.
* @return {@code true} if the given {@code Iterable} doesn't contain any elements in {@code valuesToFind} or if the given {@code Iterable} is {@code null} or empty, or if the specified {@code valuesToFind} is {@code null} or empty, {@code false} otherwise
*/
public static boolean containsNone(final Iterable> c, final Set> valuesToFind) {
if (isEmptyCollection(c) || isEmpty(valuesToFind)) {
return true;
}
return !containsAny(c, valuesToFind);
}
/**
* Checks if the given {@code Iterator} doesn't contain any elements from the specified {@code valuesToFind} Set.
*
* @param iter The {@code Iterator} to be checked for the presence of any elements in valuesToFind.
* @param valuesToFind The values to be checked for their presence in the given {@code Iterator}.
* @return {@code true} if the given {@code Iterator} doesn't contain any elements in {@code valuesToFind} or if the given {@code Iterator} is {@code null} or empty, or if the specified {@code valuesToFind} is {@code null} or empty, {@code false} otherwise
*/
public static boolean containsNone(final Iterator> iter, final Set> valuesToFind) {
if (iter == null || isEmpty(valuesToFind)) {
return true;
}
return !containsAny(iter, valuesToFind);
}
/**
* Returns a read-only slice of the input array from the specified start index to the end index.
*
* @param The type of the elements in the array.
* @param a The input array to be sliced.
* @param fromIndex The start index for the slice, inclusive.
* @param toIndex The end index for the slice, exclusive.
* @return An ImmutableList containing the slice of the input array.
* @throws IndexOutOfBoundsException if the fromIndex is negative, toIndex is larger than the length of the array, or fromIndex is larger than toIndex.
*/
public static ImmutableList slice(final T[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException {
checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR
if (isEmpty(a)) {
return ImmutableList.empty();
}
return slice(Array.asList(a), fromIndex, toIndex);
}
/**
* Returns a read-only slice of the input list from the specified start index to the end index.
*
* @param The type of the elements in the list.
* @param c The input list to be sliced.
* @param fromIndex The start index for the slice, inclusive.
* @param toIndex The end index for the slice, exclusive.
* @return An ImmutableList containing the slice of the input list.
* @throws IndexOutOfBoundsException if the fromIndex is negative, toIndex is larger than the length of the list, or fromIndex is larger than toIndex.
*/
public static ImmutableList slice(final List extends T> c, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException {
checkFromToIndex(fromIndex, toIndex, size(c));
if (isEmpty(c)) {
return ImmutableList.empty();
} else if (fromIndex == 0 && toIndex == size(c)) {
return ImmutableList.wrap(c);
}
return ImmutableList.wrap(((List) c).subList(fromIndex, toIndex));
}
/**
* Returns a read-only slice of the input collection from the specified start index to the end index.
*
* @param The type of the elements in the collection.
* @param c The input collection to be sliced.
* @param fromIndex The start index for the slice, inclusive.
* @param toIndex The end index for the slice, exclusive.
* @return An ImmutableCollection containing the slice of the input collection.
* @throws IndexOutOfBoundsException if the fromIndex is negative, toIndex is larger than the size of the collection, or fromIndex is larger than toIndex.
*/
public static ImmutableCollection slice(final Collection extends T> c, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException {
checkFromToIndex(fromIndex, toIndex, size(c));
if (isEmpty(c)) {
return ImmutableList.empty();
}
if (c instanceof List) {
return slice((List) c, fromIndex, toIndex);
}
return new Slice<>(c, fromIndex, toIndex);
}
/**
* Returns a read-only slice of the input iterator from the specified start index to the end index.
*
* @param The type of the elements in the iterator.
* @param iter The input iterator to be sliced.
* @param fromIndex The start index for the slice, inclusive.
* @param toIndex The end index for the slice, exclusive.
* @return An ObjIterator containing the slice of the input iterator.
* @throws IllegalArgumentException if the fromIndex is negative, or fromIndex is larger than toIndex.
* @see Iterators#skipAndLimit(Iterator, long, long)
*/
public static ObjIterator slice(final Iterator extends T> iter, final int fromIndex, final int toIndex) {
if (fromIndex < 0 || fromIndex > toIndex) {
throw new IllegalArgumentException("Invalid fromIndex/toIndex: [" + fromIndex + ", " + toIndex + "]");
}
if (iter == null || fromIndex == toIndex) {
return ObjIterator.empty();
}
return Iterators.skipAndLimit(iter, fromIndex, toIndex - fromIndex); // NOSONAR
}
/**
* Splits the input boolean array into sub-arrays of the specified size. The last sub-array may be smaller if the total array length is not a multiple of chunkSize.
*
* @param a The input boolean array to be split.
* @param chunkSize The desired size of each sub-array.
* @return A list of boolean sub-arrays, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
*/
public static List split(final boolean[] a, final int chunkSize) throws IllegalArgumentException {
checkArgPositive(chunkSize, "chunkSize"); //NOSONAR
if (isEmpty(a)) {
return new ArrayList<>();
}
final int len = a.length;
final List res = new ArrayList<>(len % chunkSize == 0 ? len / chunkSize : (len / chunkSize) + 1);
for (int fromIndex = 0, toIndex = a.length; fromIndex < toIndex; fromIndex += chunkSize) {
res.add(copyOfRange(a, fromIndex, fromIndex <= toIndex - chunkSize ? fromIndex + chunkSize : toIndex));
}
return res;
}
/**
* Splits the input boolean array into sub-arrays of the specified size. The last sub-array may be smaller if the length of specified range is not a multiple of chunkSize.
* The sub-arrays are created from the specified range in the input array.
*
* @param a The input boolean array to be split.
* @param fromIndex The start index for the slice of the array to be split, inclusive.
* @param toIndex The end index for the slice of the array to be split, exclusive.
* @param chunkSize The desired size of each sub-array.
* @return A list of boolean sub-arrays, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
* @throws IndexOutOfBoundsException if fromIndex is negative or larger than toIndex, toIndex is larger than the length of array
*/
public static List split(final boolean[] a, final int fromIndex, final int toIndex, final int chunkSize)
throws IllegalArgumentException, IndexOutOfBoundsException {
checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR
checkArgPositive(chunkSize, cs.chunkSize);
if (isEmpty(a) || fromIndex == toIndex) {
return new ArrayList<>();
}
final int len = toIndex - fromIndex;
final List res = new ArrayList<>(len % chunkSize == 0 ? len / chunkSize : (len / chunkSize) + 1);
for (int i = fromIndex; i < toIndex; i = i <= toIndex - chunkSize ? i + chunkSize : toIndex) {
res.add(copyOfRange(a, i, i <= toIndex - chunkSize ? i + chunkSize : toIndex));
}
return res;
}
/**
* Splits the input char array into sub-arrays of the specified size. The last sub-array may be smaller if the total array length is not a multiple of chunkSize.
*
* @param a The input char array to be split.
* @param chunkSize The desired size of each sub-array.
* @return A list of char sub-arrays, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
*/
public static List split(final char[] a, final int chunkSize) throws IllegalArgumentException {
checkArgPositive(chunkSize, cs.chunkSize);
if (isEmpty(a)) {
return new ArrayList<>();
}
final int len = a.length;
final List res = new ArrayList<>(len % chunkSize == 0 ? len / chunkSize : (len / chunkSize) + 1);
for (int fromIndex = 0, toIndex = a.length; fromIndex < toIndex; fromIndex += chunkSize) {
res.add(copyOfRange(a, fromIndex, fromIndex <= toIndex - chunkSize ? fromIndex + chunkSize : toIndex));
}
return res;
}
/**
* Splits the input char array into sub-arrays of the specified size. The last sub-array may be smaller if the length of specified range is not a multiple of chunkSize.
* The sub-arrays are created from the specified range in the input array.
*
* @param a The input char array to be split.
* @param fromIndex The start index for the slice of the array to be split, inclusive.
* @param toIndex The end index for the slice of the array to be split, exclusive.
* @param chunkSize The desired size of each sub-array.
* @return A list of char sub-arrays, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
* @throws IndexOutOfBoundsException if fromIndex is negative or larger than toIndex, toIndex is larger than the length of array
*/
public static List split(final char[] a, final int fromIndex, final int toIndex, final int chunkSize)
throws IllegalArgumentException, IndexOutOfBoundsException {
checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR
checkArgPositive(chunkSize, cs.chunkSize);
if (isEmpty(a) || fromIndex == toIndex) {
return new ArrayList<>();
}
final int len = toIndex - fromIndex;
final List res = new ArrayList<>(len % chunkSize == 0 ? len / chunkSize : (len / chunkSize) + 1);
for (int i = fromIndex; i < toIndex; i = i <= toIndex - chunkSize ? i + chunkSize : toIndex) {
res.add(copyOfRange(a, i, i <= toIndex - chunkSize ? i + chunkSize : toIndex));
}
return res;
}
/**
* Splits the input byte array into sub-arrays of the specified size. The last sub-array may be smaller if the total array length is not a multiple of chunkSize.
*
* @param a The input byte array to be split.
* @param chunkSize The desired size of each sub-array.
* @return A list of byte sub-arrays, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
*/
public static List split(final byte[] a, final int chunkSize) throws IllegalArgumentException {
checkArgPositive(chunkSize, cs.chunkSize);
if (isEmpty(a)) {
return new ArrayList<>();
}
final int len = a.length;
final List res = new ArrayList<>(len % chunkSize == 0 ? len / chunkSize : (len / chunkSize) + 1);
for (int fromIndex = 0, toIndex = a.length; fromIndex < toIndex; fromIndex += chunkSize) {
res.add(copyOfRange(a, fromIndex, fromIndex <= toIndex - chunkSize ? fromIndex + chunkSize : toIndex));
}
return res;
}
/**
* Splits the input byte array into sub-arrays of the specified size. The last sub-array may be smaller if the length of specified range is not a multiple of chunkSize.
* The sub-arrays are created from the specified range in the input array.
*
* @param a The input byte array to be split.
* @param fromIndex The start index for the slice of the array to be split, inclusive.
* @param toIndex The end index for the slice of the array to be split, exclusive.
* @param chunkSize The desired size of each sub-array.
* @return A list of byte sub-arrays, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
* @throws IndexOutOfBoundsException if fromIndex is negative or larger than toIndex, toIndex is larger than the length of array
*/
public static List split(final byte[] a, final int fromIndex, final int toIndex, final int chunkSize)
throws IllegalArgumentException, IndexOutOfBoundsException {
checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR
checkArgPositive(chunkSize, cs.chunkSize);
if (isEmpty(a) || fromIndex == toIndex) {
return new ArrayList<>();
}
final int len = toIndex - fromIndex;
final List res = new ArrayList<>(len % chunkSize == 0 ? len / chunkSize : (len / chunkSize) + 1);
for (int i = fromIndex; i < toIndex; i = i <= toIndex - chunkSize ? i + chunkSize : toIndex) {
res.add(copyOfRange(a, i, i <= toIndex - chunkSize ? i + chunkSize : toIndex));
}
return res;
}
/**
* Splits the input short array into sub-arrays of the specified size. The last sub-array may be smaller if the total array length is not a multiple of chunkSize.
*
* @param a The input short array to be split.
* @param chunkSize The desired size of each sub-array.
* @return A list of short sub-arrays, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
*/
public static List split(final short[] a, final int chunkSize) throws IllegalArgumentException {
checkArgPositive(chunkSize, cs.chunkSize);
if (isEmpty(a)) {
return new ArrayList<>();
}
final int len = a.length;
final List res = new ArrayList<>(len % chunkSize == 0 ? len / chunkSize : (len / chunkSize) + 1);
for (int fromIndex = 0, toIndex = a.length; fromIndex < toIndex; fromIndex += chunkSize) {
res.add(copyOfRange(a, fromIndex, fromIndex <= toIndex - chunkSize ? fromIndex + chunkSize : toIndex));
}
return res;
}
/**
* Splits the input short array into sub-arrays of the specified size. The last sub-array may be smaller if the length of specified range is not a multiple of chunkSize.
* The sub-arrays are created from the specified range in the input array.
*
* @param a The input short array to be split.
* @param fromIndex The start index for the slice of the array to be split, inclusive.
* @param toIndex The end index for the slice of the array to be split, exclusive.
* @param chunkSize The desired size of each sub-array.
* @return A list of short sub-arrays, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
* @throws IndexOutOfBoundsException if fromIndex is negative or larger than toIndex, toIndex is larger than the length of array
*/
public static List split(final short[] a, final int fromIndex, final int toIndex, final int chunkSize)
throws IllegalArgumentException, IndexOutOfBoundsException {
checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR
checkArgPositive(chunkSize, cs.chunkSize);
if (isEmpty(a) || fromIndex == toIndex) {
return new ArrayList<>();
}
final int len = toIndex - fromIndex;
final List res = new ArrayList<>(len % chunkSize == 0 ? len / chunkSize : (len / chunkSize) + 1);
for (int i = fromIndex; i < toIndex; i = i <= toIndex - chunkSize ? i + chunkSize : toIndex) {
res.add(copyOfRange(a, i, i <= toIndex - chunkSize ? i + chunkSize : toIndex));
}
return res;
}
/**
* Splits the input int array into sub-arrays of the specified size. The last sub-array may be smaller if the total array length is not a multiple of chunkSize.
*
* @param a The input int array to be split.
* @param chunkSize The desired size of each sub-array.
* @return A list of int sub-arrays, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
*/
public static List split(final int[] a, final int chunkSize) throws IllegalArgumentException {
checkArgPositive(chunkSize, cs.chunkSize);
if (isEmpty(a)) {
return new ArrayList<>();
}
final int len = a.length;
final List res = new ArrayList<>(len % chunkSize == 0 ? len / chunkSize : (len / chunkSize) + 1);
for (int fromIndex = 0, toIndex = a.length; fromIndex < toIndex; fromIndex += chunkSize) {
res.add(copyOfRange(a, fromIndex, fromIndex <= toIndex - chunkSize ? fromIndex + chunkSize : toIndex));
}
return res;
}
/**
* Splits the input int array into sub-arrays of the specified size. The last sub-array may be smaller if the length of specified range is not a multiple of chunkSize.
* The sub-arrays are created from the specified range in the input array.
*
* @param a The input int array to be split.
* @param fromIndex The start index for the slice of the array to be split, inclusive.
* @param toIndex The end index for the slice of the array to be split, exclusive.
* @param chunkSize The desired size of each sub-array.
* @return A list of int sub-arrays, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
* @throws IndexOutOfBoundsException if fromIndex is negative or larger than toIndex, toIndex is larger than the length of array
*/
public static List split(final int[] a, final int fromIndex, final int toIndex, final int chunkSize)
throws IllegalArgumentException, IndexOutOfBoundsException {
checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR
checkArgPositive(chunkSize, cs.chunkSize);
if (isEmpty(a) || fromIndex == toIndex) {
return new ArrayList<>();
}
final int len = toIndex - fromIndex;
final List res = new ArrayList<>(len % chunkSize == 0 ? len / chunkSize : (len / chunkSize) + 1);
for (int i = fromIndex; i < toIndex; i = i <= toIndex - chunkSize ? i + chunkSize : toIndex) {
res.add(copyOfRange(a, i, i <= toIndex - chunkSize ? i + chunkSize : toIndex));
}
return res;
}
/**
* Splits the input long array into sub-arrays of the specified size. The last sub-array may be smaller if the total array length is not a multiple of chunkSize.
*
* @param a The input long array to be split.
* @param chunkSize The desired size of each sub-array.
* @return A list of long sub-arrays, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
*/
public static List split(final long[] a, final int chunkSize) throws IllegalArgumentException {
checkArgPositive(chunkSize, cs.chunkSize);
if (isEmpty(a)) {
return new ArrayList<>();
}
final int len = a.length;
final List res = new ArrayList<>(len % chunkSize == 0 ? len / chunkSize : (len / chunkSize) + 1);
for (int fromIndex = 0, toIndex = a.length; fromIndex < toIndex; fromIndex += chunkSize) {
res.add(copyOfRange(a, fromIndex, fromIndex <= toIndex - chunkSize ? fromIndex + chunkSize : toIndex));
}
return res;
}
/**
* Splits the input long array into sub-arrays of the specified size. The last sub-array may be smaller if the length of specified range is not a multiple of chunkSize.
* The sub-arrays are created from the specified range in the input array.
*
* @param a The input long array to be split.
* @param fromIndex The start index for the slice of the array to be split, inclusive.
* @param toIndex The end index for the slice of the array to be split, exclusive.
* @param chunkSize The desired size of each sub-array.
* @return A list of long sub-arrays, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
* @throws IndexOutOfBoundsException if fromIndex is negative or larger than toIndex, toIndex is larger than the length of array
*/
public static List split(final long[] a, final int fromIndex, final int toIndex, final int chunkSize)
throws IllegalArgumentException, IndexOutOfBoundsException {
checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR
checkArgPositive(chunkSize, cs.chunkSize);
if (isEmpty(a) || fromIndex == toIndex) {
return new ArrayList<>();
}
final int len = toIndex - fromIndex;
final List res = new ArrayList<>(len % chunkSize == 0 ? len / chunkSize : (len / chunkSize) + 1);
for (int i = fromIndex; i < toIndex; i = i <= toIndex - chunkSize ? i + chunkSize : toIndex) {
res.add(copyOfRange(a, i, i <= toIndex - chunkSize ? i + chunkSize : toIndex));
}
return res;
}
/**
* Splits the input float array into sub-arrays of the specified size. The last sub-array may be smaller if the total array length is not a multiple of chunkSize.
*
* @param a The input float array to be split.
* @param chunkSize The desired size of each sub-array.
* @return A list of float sub-arrays, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
*/
public static List split(final float[] a, final int chunkSize) throws IllegalArgumentException {
checkArgPositive(chunkSize, cs.chunkSize);
if (isEmpty(a)) {
return new ArrayList<>();
}
final int len = a.length;
final List res = new ArrayList<>(len % chunkSize == 0 ? len / chunkSize : (len / chunkSize) + 1);
for (int fromIndex = 0, toIndex = a.length; fromIndex < toIndex; fromIndex += chunkSize) {
res.add(copyOfRange(a, fromIndex, fromIndex <= toIndex - chunkSize ? fromIndex + chunkSize : toIndex));
}
return res;
}
/**
* Splits the input float array into sub-arrays of the specified size. The last sub-array may be smaller if the length of specified range is not a multiple of chunkSize.
* The sub-arrays are created from the specified range in the input array.
*
* @param a The input float array to be split.
* @param fromIndex The start index for the slice of the array to be split, inclusive.
* @param toIndex The end index for the slice of the array to be split, exclusive.
* @param chunkSize The desired size of each sub-array.
* @return A list of float sub-arrays, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
* @throws IndexOutOfBoundsException if fromIndex is negative or larger than toIndex, toIndex is larger than the length of array
*/
public static List split(final float[] a, final int fromIndex, final int toIndex, final int chunkSize)
throws IllegalArgumentException, IndexOutOfBoundsException {
checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR
checkArgPositive(chunkSize, cs.chunkSize);
if (isEmpty(a) || fromIndex == toIndex) {
return new ArrayList<>();
}
final int len = toIndex - fromIndex;
final List res = new ArrayList<>(len % chunkSize == 0 ? len / chunkSize : (len / chunkSize) + 1);
for (int i = fromIndex; i < toIndex; i = i <= toIndex - chunkSize ? i + chunkSize : toIndex) {
res.add(copyOfRange(a, i, i <= toIndex - chunkSize ? i + chunkSize : toIndex));
}
return res;
}
/**
* Splits the input double array into sub-arrays of the specified size. The last sub-array may be smaller if the total array length is not a multiple of chunkSize.
*
* @param a The input double array to be split.
* @param chunkSize The desired size of each sub-array.
* @return A list of double sub-arrays, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
*/
public static List split(final double[] a, final int chunkSize) throws IllegalArgumentException {
checkArgPositive(chunkSize, cs.chunkSize);
if (isEmpty(a)) {
return new ArrayList<>();
}
final int len = a.length;
final List res = new ArrayList<>(len % chunkSize == 0 ? len / chunkSize : (len / chunkSize) + 1);
for (int fromIndex = 0, toIndex = a.length; fromIndex < toIndex; fromIndex += chunkSize) {
res.add(copyOfRange(a, fromIndex, fromIndex <= toIndex - chunkSize ? fromIndex + chunkSize : toIndex));
}
return res;
}
/**
* Splits the input double array into sub-arrays of the specified size. The last sub-array may be smaller if the length of specified range is not a multiple of chunkSize.
* The sub-arrays are created from the specified range in the input array.
*
* @param a The input double array to be split.
* @param fromIndex The start index for the slice of the array to be split, inclusive.
* @param toIndex The end index for the slice of the array to be split, exclusive.
* @param chunkSize The desired size of each sub-array.
* @return A list of double sub-arrays, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
* @throws IndexOutOfBoundsException if fromIndex is negative or larger than toIndex, toIndex is larger than the length of array
*/
public static List split(final double[] a, final int fromIndex, final int toIndex, final int chunkSize)
throws IllegalArgumentException, IndexOutOfBoundsException {
checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR
checkArgPositive(chunkSize, cs.chunkSize);
if (isEmpty(a) || fromIndex == toIndex) {
return new ArrayList<>();
}
final int len = toIndex - fromIndex;
final List res = new ArrayList<>(len % chunkSize == 0 ? len / chunkSize : (len / chunkSize) + 1);
for (int i = fromIndex; i < toIndex; i = i <= toIndex - chunkSize ? i + chunkSize : toIndex) {
res.add(copyOfRange(a, i, i <= toIndex - chunkSize ? i + chunkSize : toIndex));
}
return res;
}
/**
* Splits the input array into sub-arrays of the specified size. The last sub-array may be smaller if the total array length is not a multiple of chunkSize.
*
* @param The type of the elements in the array.
* @param a The input array to be split.
* @param chunkSize The desired size of each sub-array.
* @return A list of sub-arrays, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
*/
public static List split(final T[] a, final int chunkSize) throws IllegalArgumentException {
checkArgPositive(chunkSize, cs.chunkSize);
if (isEmpty(a)) {
return new ArrayList<>();
}
final int len = a.length;
final List res = new ArrayList<>(len % chunkSize == 0 ? len / chunkSize : (len / chunkSize) + 1);
for (int fromIndex = 0, toIndex = a.length; fromIndex < toIndex; fromIndex += chunkSize) {
res.add(copyOfRange(a, fromIndex, fromIndex <= toIndex - chunkSize ? fromIndex + chunkSize : toIndex));
}
return res;
}
/**
* Splits the input array into sub-arrays of the specified size. The last sub-array may be smaller if the length of specified range is not a multiple of chunkSize.
* The sub-arrays are created from the specified range in the input array.
*
* @param a The input array to be split.
* @param fromIndex The start index for the slice of the array to be split, inclusive.
* @param toIndex The end index for the slice of the array to be split, exclusive.
* @param chunkSize The desired size of each sub-array.
* @return A list of sub-arrays, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
* @throws IndexOutOfBoundsException if fromIndex is negative or larger than toIndex, toIndex is larger than the length of array
*/
public static List split(final T[] a, final int fromIndex, final int toIndex, final int chunkSize)
throws IllegalArgumentException, IndexOutOfBoundsException {
checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR
checkArgPositive(chunkSize, cs.chunkSize);
if (isEmpty(a) || fromIndex == toIndex) {
return new ArrayList<>();
}
final int len = toIndex - fromIndex;
final List res = new ArrayList<>(len % chunkSize == 0 ? len / chunkSize : (len / chunkSize) + 1);
for (int i = fromIndex; i < toIndex; i = i <= toIndex - chunkSize ? i + chunkSize : toIndex) {
res.add(copyOfRange(a, i, i <= toIndex - chunkSize ? i + chunkSize : toIndex));
}
return res;
}
/**
* Splits the input collection into sub-collections of the specified size. The last sub-collection may be smaller if the total collection size is not a multiple of chunkSize.
*
* @param The type of the elements in the collection.
* @param c The input collection to be split.
* @param chunkSize The desired size of each sub-collection.
* @return A list of sub-collections, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
*/
public static List> split(final Collection extends T> c, final int chunkSize) throws IllegalArgumentException {
checkArgPositive(chunkSize, cs.chunkSize);
if (isEmpty(c)) {
return new ArrayList<>();
}
return split(c, 0, c.size(), chunkSize);
}
/**
* Splits the input collection into sub-collections of the specified size. The last sub-collection may be smaller if the length of specified range is not a multiple of chunkSize.
* The sub-collections are created from the specified range in the input collection.
*
* @param The type of the elements in the collection.
* @param c The input collection to be split.
* @param fromIndex The start index for the slice of the collection to be split, inclusive.
* @param toIndex The end index for the slice of the collection to be split, exclusive.
* @param chunkSize The desired size of each sub-collection.
* @return A list of sub-collections, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
* @throws IndexOutOfBoundsException if fromIndex is negative or larger than toIndex, or toIndex is greater than the size of collection.
*/
public static List> split(final Collection extends T> c, final int fromIndex, final int toIndex, final int chunkSize)
throws IllegalArgumentException, IndexOutOfBoundsException {
checkFromToIndex(fromIndex, toIndex, size(c));
checkArgPositive(chunkSize, cs.chunkSize);
if (isEmpty(c) || fromIndex == toIndex) {
return new ArrayList<>();
}
final int len = toIndex - fromIndex;
final List> res = new ArrayList<>(len % chunkSize == 0 ? len / chunkSize : (len / chunkSize) + 1);
if (c instanceof List) {
final List list = (List) c;
for (int i = fromIndex; i < toIndex; i = i <= toIndex - chunkSize ? i + chunkSize : toIndex) {
res.add(list.subList(i, i <= toIndex - chunkSize ? i + chunkSize : toIndex));
}
} else {
final Iterator extends T> iter = c.iterator();
for (int i = 0; i < toIndex;) {
if (i < fromIndex) {
iter.next();
i++;
continue;
}
final List subList = new ArrayList<>(min(chunkSize, toIndex - i));
for (final int j = i <= toIndex - chunkSize ? i + chunkSize : toIndex; i < j; i++) {
subList.add(iter.next());
}
res.add(subList);
}
}
return res;
}
/**
* Splits the input iterable into sub-collections of the specified size. The last sub-collection may be smaller if the total iterable size is not a multiple of chunkSize.
*
* @param The type of the elements in the iterable.
* @param c The input iterable to be split.
* @param chunkSize The desired size of each sub-collection.
* @return A list of sub-collections, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
*/
public static List> split(final Iterable extends T> c, final int chunkSize) throws IllegalArgumentException {
checkArgPositive(chunkSize, cs.chunkSize);
if (isEmptyCollection(c)) {
return new ArrayList<>();
} else if (c instanceof Collection) {
final Collection coll = (Collection) c;
return split(coll, 0, coll.size(), chunkSize);
} else {
return toList(split(c.iterator(), chunkSize));
}
}
/**
* Splits the input iterator into sub-collections of the specified size. The last sub-collection may be smaller if the total iterator size is not a multiple of chunkSize.
*
* @param The type of the elements in the iterator.
* @param iter The input iterator to be split.
* @param chunkSize The desired size of each sub-collection.
* @return An iterator of sub-collections, each of size chunkSize (except possibly for the last one).
* @throws IllegalArgumentException if chunkSize is not a positive integer.
*/
public static ObjIterator> split(final Iterator extends T> iter, final int chunkSize) throws IllegalArgumentException {
checkArgument(chunkSize > 0, "'chunkSize' must be greater than 0, can't be: %s", chunkSize);
if (iter == null) {
return ObjIterator.empty();
}
return new ObjIterator<>() {
private final Iterator extends T> iterator = iter;
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public List next() {
if (!hasNext()) {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
final List next = new ArrayList<>(chunkSize);
for (int i = 0; i < chunkSize && iterator.hasNext(); i++) {
next.add(iterator.next());
}
return next;
}
};
}
/**
* Returns consecutive substring of the specified string, each of the same length (the final list may be smaller),
* or an empty array if the specified string is {@code null} or empty.
*
* @param str
* @param chunkSize the desired size of each sub String (the last may be smaller).
* @return
* @throws IllegalArgumentException
*/
public static List split(final CharSequence str, final int chunkSize) throws IllegalArgumentException {
checkArgPositive(chunkSize, cs.chunkSize);
if (Strings.isEmpty(str)) {
return new ArrayList<>();
}
return split(str, 0, str.length(), chunkSize);
}
/**
* Returns consecutive substring of the specified string, each of the same length (the final list may be smaller),
* or an empty array if the specified string is {@code null} or empty.
*
* @param str
* @param fromIndex
* @param toIndex
* @param chunkSize the desired size of each sub String (the last may be smaller).
* @return
* @throws IllegalArgumentException
* @throws IndexOutOfBoundsException
*/
public static List split(final CharSequence str, final int fromIndex, final int toIndex, final int chunkSize)
throws IllegalArgumentException, IndexOutOfBoundsException {
checkFromToIndex(fromIndex, toIndex, len(str));
checkArgPositive(chunkSize, cs.chunkSize);
if (Strings.isEmpty(str)) {
return new ArrayList<>();
}
final int len = toIndex - fromIndex;
final List res = new ArrayList<>(len % chunkSize == 0 ? len / chunkSize : (len / chunkSize) + 1);
for (int i = fromIndex; i < toIndex; i = i <= toIndex - chunkSize ? i + chunkSize : toIndex) {
res.add(str.subSequence(i, i <= toIndex - chunkSize ? i + chunkSize : toIndex).toString());
}
return res;
}
/**
* Splits the total size into chunks based on the specified maximum chunk count.
*
* The size of the chunks is larger first.
*
* The size of returned List may be less than the specified {@code maxChunkCount} if the input {@code totalSize} is less than {@code maxChunkCount}.
*
* @param the type of the elements in the resulting stream
* @param totalSize the total size to be split. It could be the size of an array, list, etc.
* @param maxChunkCount the maximum number of chunks to split into
* @return a Stream of the mapped chunk values
* @throws IllegalArgumentException if {@code totalSize} is negative or {@code maxChunkCount} is not positive.
* @see #splitByChunkCount(int, int, boolean, IntBiFunction)
*/
public static List splitByChunkCount(final int totalSize, final int maxChunkCount, final IntBiFunction extends T> func) {
return splitByChunkCount(totalSize, maxChunkCount, false, func);
}
/**
* Splits the total size into chunks based on the specified maximum chunk count.
*
* The size of the chunks can be either smaller or larger first based on the flag.
*
* The size of returned List may be less than the specified {@code maxChunkCount} if the input {@code totalSize} is less than {@code maxChunkCount}.
*
*
*
* final int[] a = Array.rangeClosed(1, 7);
* splitByChunkCount(7, 5, true, (fromIndex, toIndex) -> copyOfRange(a, fromIndex, toIndex)); // [[1], [2], [3], [4, 5], [6, 7]]
* splitByChunkCount(7, 5, false, (fromIndex, toIndex) -> copyOfRange(a, fromIndex, toIndex)); // [[1, 2], [3, 4], [5], [6], [7]]
*
*
*
* @param the type of the elements in the resulting stream
* @param totalSize the total size to be split. It could be the size of an array, list, etc.
* @param maxChunkCount the maximum number of chunks to split into
* @param sizeSmallerFirst if {@code true}, smaller chunks will be created first; otherwise, larger chunks will be created first
* @param func a function to map the chunk from and to index to an element in the resulting stream
* @return a Stream of the mapped chunk values
* @throws IllegalArgumentException if {@code totalSize} is negative or {@code maxChunkCount} is not positive.
* @see #splitByChunkCount(Collection, int, boolean)
* @see Stream#splitByChunkCount(int, int, boolean, IntBiFunction)
* @see IntStream#splitByChunkCount(int, int, IntBinaryOperator)
*/
public static List splitByChunkCount(final int totalSize, final int maxChunkCount, final boolean sizeSmallerFirst,
final IntBiFunction extends T> func) {
N.checkArgNotNegative(totalSize, cs.totalSize);
N.checkArgPositive(maxChunkCount, cs.maxChunkCount);
//noinspection resource
return Stream. splitByChunkCount(totalSize, maxChunkCount, sizeSmallerFirst, func).toList();
}
/**
* Splits the input collection into sub-lists based on the specified maximum chunk count.
*
* The size of the chunks is larger first.
*
* The size of returned List may be less than the specified {@code maxChunkCount} if the input Collection size is less than {@code maxChunkCount}.
*
* @param the type of elements in the input collection
* @param c the input collection to be split
* @param maxChunkCount the maximum number of chunks to split into
* @return a list of sub-lists.
* @throws IllegalArgumentException if {@code maxChunkCount} is not positive.
* @see #splitByChunkCount(Collection, int, boolean)
*/
public static List> splitByChunkCount(final Collection extends T> c, final int maxChunkCount) {
return splitByChunkCount(c, maxChunkCount, false);
}
/**
* Splits the input collection into sub-lists based on the specified maximum chunk count.
*
* The size of the chunks can be either smaller or larger first based on the flag.
*
* The size of returned List may be less than the specified {@code maxChunkCount} if the input Collection size is less than {@code maxChunkCount}.
*
*
*
* final List c = N.asList(1, 2, 3, 4, 5, 6, 7);
* splitByChunkCount(c, 5, true); // [[1], [2], [3], [4, 5], [6, 7]]
* splitByChunkCount(c, 5, false); // [[1, 2], [3, 4], [5], [6], [7]]
*
*
*
* @param the type of elements in the input collection
* @param c the input collection to be split
* @param maxChunkCount the maximum number of chunks to split into
* @param sizeSmallerFirst if {@code true}, smaller chunks will be created first; otherwise, larger chunks will be created first
* @return a list of sub-lists.
* @throws IllegalArgumentException if {@code maxChunkCount} is not positive.
* @see #splitByChunkCount(int, int, boolean, IntBiFunction)
* @see Stream#splitByChunkCount(int, int, boolean, IntBiFunction)
* @see IntStream#splitByChunkCount(int, int, boolean, IntBinaryOperator)
*/
public static List> splitByChunkCount(final Collection extends T> c, final int maxChunkCount, final boolean sizeSmallerFirst) {
N.checkArgPositive(maxChunkCount, cs.maxChunkCount);
if (isEmpty(c)) {
return new ArrayList<>();
}
IntBiFunction> func = null;
if (c instanceof List) { // NOSONAR
final List list = (List) c; // NOSONAR
func = list::subList;
} else {
final Iterator extends T> iter = c.iterator();
// Only used in below line to call splitByChunkCount.
func = (fromIndex, toIndex) -> {
final List subList = new ArrayList<>(toIndex - fromIndex);
for (int i = fromIndex; i < toIndex; i++) {
subList.add(iter.next());
}
return subList;
};
}
return splitByChunkCount(c.size(), maxChunkCount, sizeSmallerFirst, func);
}
/**
* Concatenates two boolean arrays into a new array.
*
* @param a The first boolean array.
* @param b The second boolean array.
* @return A new boolean array that contains the elements of a followed by the elements of b .
* If both a and b are empty or {@code null}, an empty array is returned.
* If a is empty or {@code null}, a clone of b is returned.
* If b is empty or {@code null}, a clone of a is returned.
*/
public static boolean[] concat(final boolean[] a, final boolean[] b) {
if (isEmpty(a)) {
return isEmpty(b) ? EMPTY_BOOLEAN_ARRAY : b.clone();
} else if (isEmpty(b)) {
return isEmpty(a) ? EMPTY_BOOLEAN_ARRAY : a.clone();
}
final boolean[] c = new boolean[a.length + b.length];
copy(a, 0, c, 0, a.length);
copy(b, 0, c, a.length, b.length);
return c;
}
/**
* Concatenates multiple boolean arrays into a new array.
*
* @param aa The boolean arrays to be concatenated.
* @return A new boolean array that contains the elements of each array in {@code 'aa'} in the same order.
* If {@code 'aa'} is empty or {@code null}, an empty array is returned.
* If {@code 'aa'} contains only one array, a clone of this array is returned.
*/
@SafeVarargs
public static boolean[] concat(final boolean[]... aa) {
if (isEmpty(aa)) {
return EMPTY_BOOLEAN_ARRAY;
} else if (aa.length == 1) {
return isEmpty(aa[0]) ? EMPTY_BOOLEAN_ARRAY : aa[0].clone();
}
int len = 0;
for (final boolean[] a : aa) {
if (isEmpty(a)) {
continue;
}
len += a.length;
}
final boolean[] c = new boolean[len];
int fromIndex = 0;
for (final boolean[] a : aa) {
if (isEmpty(a)) {
continue;
}
System.arraycopy(a, 0, c, fromIndex, a.length);
fromIndex += a.length;
}
return c;
}
/**
* Concatenates two char arrays into a new array.
*
* @param a The first char array.
* @param b The second char array.
* @return A new char array that contains the elements of a followed by the elements of b .
* If both a and b are empty or {@code null}, an empty array is returned.
* If a is empty or {@code null}, a clone of b is returned.
* If b is empty or {@code null}, a clone of a is returned.
*/
public static char[] concat(final char[] a, final char[] b) {
if (isEmpty(a)) {
return isEmpty(b) ? EMPTY_CHAR_ARRAY : b.clone();
} else if (isEmpty(b)) {
return isEmpty(a) ? EMPTY_CHAR_ARRAY : a.clone();
}
final char[] c = new char[a.length + b.length];
copy(a, 0, c, 0, a.length);
copy(b, 0, c, a.length, b.length);
return c;
}
/**
* Concatenates multiple char arrays into a new array.
*
* @param aa The char arrays to be concatenated.
* @return A new char array that contains the elements of each array in {@code 'aa'} in the same order.
* If {@code 'aa'} is empty or {@code null}, an empty array is returned.
* If {@code 'aa'} contains only one array, a clone of this array is returned.
*/
@SafeVarargs
public static char[] concat(final char[]... aa) {
if (isEmpty(aa)) {
return EMPTY_CHAR_ARRAY;
} else if (aa.length == 1) {
return isEmpty(aa[0]) ? EMPTY_CHAR_ARRAY : aa[0].clone();
}
int len = 0;
for (final char[] a : aa) {
if (isEmpty(a)) {
continue;
}
len += a.length;
}
final char[] c = new char[len];
int fromIndex = 0;
for (final char[] a : aa) {
if (isEmpty(a)) {
continue;
}
System.arraycopy(a, 0, c, fromIndex, a.length);
fromIndex += a.length;
}
return c;
}
/**
* Concatenates two byte arrays into a new array.
*
* @param a The first byte array.
* @param b The second byte array.
* @return A new byte array that contains the elements of a followed by the elements of b .
* If both a and b are empty or {@code null}, an empty array is returned.
* If a is empty or {@code null}, a clone of b is returned.
* If b is empty or {@code null}, a clone of a is returned.
*/
public static byte[] concat(final byte[] a, final byte[] b) {
if (isEmpty(a)) {
return isEmpty(b) ? EMPTY_BYTE_ARRAY : b.clone();
} else if (isEmpty(b)) {
return isEmpty(a) ? EMPTY_BYTE_ARRAY : a.clone();
}
final byte[] c = new byte[a.length + b.length];
copy(a, 0, c, 0, a.length);
copy(b, 0, c, a.length, b.length);
return c;
}
/**
* Concatenates multiple byte arrays into a new array.
*
* @param aa The byte arrays to be concatenated.
* @return A new byte array that contains the elements of each array in {@code 'aa'} in the same order.
* If {@code 'aa'} is empty or {@code null}, an empty array is returned.
* If {@code 'aa'} contains only one array, a clone of this array is returned.
*/
@SafeVarargs
public static byte[] concat(final byte[]... aa) {
if (isEmpty(aa)) {
return EMPTY_BYTE_ARRAY;
} else if (aa.length == 1) {
return isEmpty(aa[0]) ? EMPTY_BYTE_ARRAY : aa[0].clone();
}
int len = 0;
for (final byte[] a : aa) {
if (isEmpty(a)) {
continue;
}
len += a.length;
}
final byte[] c = new byte[len];
int fromIndex = 0;
for (final byte[] a : aa) {
if (isEmpty(a)) {
continue;
}
System.arraycopy(a, 0, c, fromIndex, a.length);
fromIndex += a.length;
}
return c;
}
/**
* Concatenates two short arrays into a new array.
*
* @param a The first short array.
* @param b The second short array.
* @return A new short array that contains the elements of a followed by the elements of b .
* If both a and b are empty or {@code null}, an empty array is returned.
* If a is empty or {@code null}, a clone of b is returned.
* If b is empty or {@code null}, a clone of a is returned.
*/
public static short[] concat(final short[] a, final short[] b) {
if (isEmpty(a)) {
return isEmpty(b) ? EMPTY_SHORT_ARRAY : b.clone();
} else if (isEmpty(b)) {
return isEmpty(a) ? EMPTY_SHORT_ARRAY : a.clone();
}
final short[] c = new short[a.length + b.length];
copy(a, 0, c, 0, a.length);
copy(b, 0, c, a.length, b.length);
return c;
}
/**
* Concatenates multiple short arrays into a new array.
*
* @param aa The short arrays to be concatenated.
* @return A new short array that contains the elements of each array in {@code 'aa'} in the same order.
* If {@code 'aa'} is empty or {@code null}, an empty array is returned.
* If {@code 'aa'} contains only one array, a clone of this array is returned.
*/
@SafeVarargs
public static short[] concat(final short[]... aa) {
if (isEmpty(aa)) {
return EMPTY_SHORT_ARRAY;
} else if (aa.length == 1) {
return isEmpty(aa[0]) ? EMPTY_SHORT_ARRAY : aa[0].clone();
}
int len = 0;
for (final short[] a : aa) {
if (isEmpty(a)) {
continue;
}
len += a.length;
}
final short[] c = new short[len];
int fromIndex = 0;
for (final short[] a : aa) {
if (isEmpty(a)) {
continue;
}
System.arraycopy(a, 0, c, fromIndex, a.length);
fromIndex += a.length;
}
return c;
}
/**
* Concatenates two int arrays into a new array.
*
* @param a The first int array.
* @param b The second int array.
* @return A new int array that contains the elements of a followed by the elements of b .
* If both a and b are empty or {@code null}, an empty array is returned.
* If a is empty or {@code null}, a clone of b is returned.
* If b is empty or {@code null}, a clone of a is returned.
*/
public static int[] concat(final int[] a, final int[] b) {
if (isEmpty(a)) {
return isEmpty(b) ? EMPTY_INT_ARRAY : b.clone();
} else if (isEmpty(b)) {
return isEmpty(a) ? EMPTY_INT_ARRAY : a.clone();
}
final int[] c = new int[a.length + b.length];
copy(a, 0, c, 0, a.length);
copy(b, 0, c, a.length, b.length);
return c;
}
/**
* Concatenates multiple int arrays into a new array.
*
* @param aa The int arrays to be concatenated.
* @return A new int array that contains the elements of each array in {@code 'aa'} in the same order.
* If {@code 'aa'} is empty or {@code null}, an empty array is returned.
* If {@code 'aa'} contains only one array, a clone of this array is returned.
*/
@SafeVarargs
public static int[] concat(final int[]... aa) {
if (isEmpty(aa)) {
return EMPTY_INT_ARRAY;
} else if (aa.length == 1) {
return isEmpty(aa[0]) ? EMPTY_INT_ARRAY : aa[0].clone();
}
int len = 0;
for (final int[] a : aa) {
if (isEmpty(a)) {
continue;
}
len += a.length;
}
final int[] c = new int[len];
int fromIndex = 0;
for (final int[] a : aa) {
if (isEmpty(a)) {
continue;
}
System.arraycopy(a, 0, c, fromIndex, a.length);
fromIndex += a.length;
}
return c;
}
/**
* Concatenates two long arrays into a new array.
*
* @param a The first long array.
* @param b The second long array.
* @return A new long array that contains the elements of a followed by the elements of b .
* If both a and b are empty or {@code null}, an empty array is returned.
* If a is empty or {@code null}, a clone of b is returned.
* If b is empty or {@code null}, a clone of a is returned.
*/
public static long[] concat(final long[] a, final long[] b) {
if (isEmpty(a)) {
return isEmpty(b) ? EMPTY_LONG_ARRAY : b.clone();
} else if (isEmpty(b)) {
return isEmpty(a) ? EMPTY_LONG_ARRAY : a.clone();
}
final long[] c = new long[a.length + b.length];
copy(a, 0, c, 0, a.length);
copy(b, 0, c, a.length, b.length);
return c;
}
/**
* Concatenates multiple long arrays into a new array.
*
* @param aa The long arrays to be concatenated.
* @return A new long array that contains the elements of each array in {@code 'aa'} in the same order.
* If {@code 'aa'} is empty or {@code null}, an empty array is returned.
* If {@code 'aa'} contains only one array, a clone of this array is returned.
*/
@SafeVarargs
public static long[] concat(final long[]... aa) {
if (isEmpty(aa)) {
return EMPTY_LONG_ARRAY;
} else if (aa.length == 1) {
return isEmpty(aa[0]) ? EMPTY_LONG_ARRAY : aa[0].clone();
}
int len = 0;
for (final long[] a : aa) {
if (isEmpty(a)) {
continue;
}
len += a.length;
}
final long[] c = new long[len];
int fromIndex = 0;
for (final long[] a : aa) {
if (isEmpty(a)) {
continue;
}
System.arraycopy(a, 0, c, fromIndex, a.length);
fromIndex += a.length;
}
return c;
}
/**
* Concatenates two float arrays into a new array.
*
* @param a The first float array.
* @param b The second float array.
* @return A new float array that contains the elements of a followed by the elements of b .
* If both a and b are empty or {@code null}, an empty array is returned.
* If a is empty or {@code null}, a clone of b is returned.
* If b is empty or {@code null}, a clone of a is returned.
*/
public static float[] concat(final float[] a, final float[] b) {
if (isEmpty(a)) {
return isEmpty(b) ? EMPTY_FLOAT_ARRAY : b.clone();
} else if (isEmpty(b)) {
return isEmpty(a) ? EMPTY_FLOAT_ARRAY : a.clone();
}
final float[] c = new float[a.length + b.length];
copy(a, 0, c, 0, a.length);
copy(b, 0, c, a.length, b.length);
return c;
}
/**
* Concatenates multiple float arrays into a new array.
*
* @param aa The float arrays to be concatenated.
* @return A new float array that contains the elements of each array in {@code 'aa'} in the same order.
* If {@code 'aa'} is empty or {@code null}, an empty array is returned.
* If {@code 'aa'} contains only one array, a clone of this array is returned.
*/
@SafeVarargs
public static float[] concat(final float[]... aa) {
if (isEmpty(aa)) {
return EMPTY_FLOAT_ARRAY;
} else if (aa.length == 1) {
return isEmpty(aa[0]) ? EMPTY_FLOAT_ARRAY : aa[0].clone();
}
int len = 0;
for (final float[] a : aa) {
if (isEmpty(a)) {
continue;
}
len += a.length;
}
final float[] c = new float[len];
int fromIndex = 0;
for (final float[] a : aa) {
if (isEmpty(a)) {
continue;
}
System.arraycopy(a, 0, c, fromIndex, a.length);
fromIndex += a.length;
}
return c;
}
/**
* Concatenates two double arrays into a new array.
*
* @param a The first double array.
* @param b The second double array.
* @return A new double array that contains the elements of a followed by the elements of b .
* If both a and b are empty or {@code null}, an empty array is returned.
* If a is empty or {@code null}, a clone of b is returned.
* If b is empty or {@code null}, a clone of a is returned.
*/
public static double[] concat(final double[] a, final double[] b) {
if (isEmpty(a)) {
return isEmpty(b) ? EMPTY_DOUBLE_ARRAY : b.clone();
} else if (isEmpty(b)) {
return isEmpty(a) ? EMPTY_DOUBLE_ARRAY : a.clone();
}
final double[] c = new double[a.length + b.length];
copy(a, 0, c, 0, a.length);
copy(b, 0, c, a.length, b.length);
return c;
}
/**
* Concatenates multiple double arrays into a new array.
*
* @param aa The double arrays to be concatenated.
* @return A new double array that contains the elements of each array in {@code 'aa'} in the same order.
* If {@code 'aa'} is empty or {@code null}, an empty array is returned.
* If {@code 'aa'} contains only one array, a clone of this array is returned.
*/
@SafeVarargs
public static double[] concat(final double[]... aa) {
if (isEmpty(aa)) {
return EMPTY_DOUBLE_ARRAY;
} else if (aa.length == 1) {
return isEmpty(aa[0]) ? EMPTY_DOUBLE_ARRAY : aa[0].clone();
}
int len = 0;
for (final double[] a : aa) {
if (isEmpty(a)) {
continue;
}
len += a.length;
}
final double[] c = new double[len];
int fromIndex = 0;
for (final double[] a : aa) {
if (isEmpty(a)) {
continue;
}
System.arraycopy(a, 0, c, fromIndex, a.length);
fromIndex += a.length;
}
return c;
}
/**
* Concatenates two arrays into a new array.
*
* @param The type of the elements in the arrays.
* @param a The first array.
* @param b The second array.
* @return A new array that contains the elements of a followed by the elements of b .
* If both a and b are empty or {@code null}, a is returned.
* If a is empty or {@code null}, a clone of b is returned.
* If b is empty or {@code null}, a clone of a is returned.
*
* @see #merge(Object[], Object[], BiFunction)
*/
public static T[] concat(final T[] a, final T[] b) {
if (isEmpty(a)) {
return isEmpty(b) ? a : b.clone();
} else if (isEmpty(b)) {
return a.clone();
}
final T[] c = newArray(a.getClass().getComponentType(), a.length + b.length);
copy(a, 0, c, 0, a.length);
copy(b, 0, c, a.length, b.length);
return c;
}
/**
* Concatenates multiple arrays into a new array.
*
* @param The type of the elements in the arrays.
* @param aa The arrays to be concatenated.
* @return A new array that contains the elements of each array in {@code 'aa'} in the same order. If all the specified arrays are {@code null}, {@code null} is returned.
* @see System#arraycopy(Object, int, Object, int, int)
*/
@MayReturnNull
@SafeVarargs
public static T[] concat(final T[]... aa) { // throws IllegalArgumentException {
// checkArgNotNull(aa, cs.arrays); // if aa can't be null, what's about method: concat(final T[] a, final T[] b)? a and b can't be null too?
if (aa == null) {
return null; // NOSONAR
} else if (aa.length == 0) {
return newArray(aa.getClass().getComponentType().getComponentType(), 0);
} else if (aa.length == 1) {
return aa[0] == null ? newArray(aa.getClass().getComponentType().getComponentType(), 0) : aa[0].clone();
}
int len = 0;
for (final T[] a : aa) {
if (isEmpty(a)) {
continue;
}
len += a.length;
}
final T[] c = newArray(aa.getClass().getComponentType().getComponentType(), len);
int fromIndex = 0;
for (final T[] a : aa) {
if (isEmpty(a)) {
continue;
}
System.arraycopy(a, 0, c, fromIndex, a.length);
fromIndex += a.length;
}
return c;
}
/**
* Concatenates two iterables into a new list.
*
* @param The type of the elements in the {@code iterables}.
* @param a The first iterable.
* @param b The second iterable.
* @return A new list that contains the elements of a followed by the elements of b .
* If both a and b are empty or {@code null}, an empty list is returned.
* If a is empty or {@code null}, a list containing the elements of b is returned.
* If b is empty or {@code null}, a list containing the elements of a is returned.
*
* @see #merge(Iterable, Iterable, BiFunction)
*/
public static List concat(final Iterable extends T> a, final Iterable extends T> b) {
return concat(Arrays.asList(a, b));
}
/**
* Concatenates multiple iterables into a new list.
*
* @param The type of the elements in the {@code iterables}.
* @param a The iterables to be concatenated.
* @return A new list that contains the elements of each iterable in a in the same order.
* If a is empty or {@code null}, an empty list is returned.
* If a contains only one iterable, a list containing the elements of this iterable is returned.
*
* @see #merge(Collection, BiFunction)
* @see #merge(Collection, BiFunction, IntFunction)
*/
@SafeVarargs
public static List concat(final Iterable extends T>... a) {
if (isEmpty(a)) {
return new ArrayList<>();
}
return concat(Arrays.asList(a));
}
/**
* Concatenates multiple iterables into a new list.
*
* @param The type of the elements in the {@code iterables}.
* @param c The collection of iterable to be concatenated.
* @return A new list that contains the elements of each iterable in c in the same order.
* If c is empty or {@code null}, an empty list is returned.
* If c contains only one iterable, a list containing the elements of this iterable is returned.
*
* @see #merge(Collection, BiFunction)
* @see #merge(Collection, BiFunction, IntFunction)
*/
public static List concat(final Collection extends Iterable extends T>> c) {
return concat(c, Factory.ofList());
}
/**
* Concatenates multiple iterables into a new collection.
*
* @param The type of the elements in the {@code iterables}.
* @param The type of the collection to be returned.
* @param c The collection of iterable to be concatenated.
* @param supplier The function that generates a new instance of the return collection.
* @return A new collection that contains the elements of each iterable in c in the same order.
* The type of the returned collection is determined by the supplier function.
* If c is empty or {@code null}, an empty collection is returned.
* If c contains only one iterable, a collection containing the elements of this iterable is returned.
*
* @see #merge(Collection, BiFunction)
* @see #merge(Collection, BiFunction, IntFunction)
*/
public static > C concat(final Collection extends Iterable extends T>> c, final IntFunction extends C> supplier) {
if (isEmpty(c)) {
return supplier.apply(0);
}
long count = 0;
for (final Iterable extends T> e : c) {
count += getSizeOrDefault(e, 0);
}
final C result = supplier.apply(Numbers.toIntExact(count));
for (final Iterable extends T> e : c) {
if (e != null) {
if (e instanceof Collection) {
result.addAll((Collection) e);
} else {
for (final T t : e) {
result.add(t);
}
}
}
}
return result;
}
/**
* Concatenates two iterators into a new ObjIterator.
*
* @param The type of the elements in the iterators.
* @param a The first iterator.
* @param b The second iterator.
* @return A new ObjIterator that contains the elements of a followed by the elements of b .
* @see Iterators#concat(Iterator...)
*/
public static ObjIterator concat(final Iterator extends T> a, final Iterator extends T> b) {
return Iterators.concat(a, b);
}
/**
* Concatenates multiple iterators into a new ObjIterator.
*
* @param The type of the elements in the iterators.
* @param a The array of iterators to be concatenated.
* @return A new ObjIterator that contains the elements of each iterator in a in the same order.
* @see Iterators#concat(Iterator...)
*/
@SafeVarargs
public static ObjIterator concat(final Iterator extends T>... a) {
return Iterators.concat(a);
}
/**
* Flattens a two-dimensional boolean array into a one-dimensional boolean array.
*
* @param a The two-dimensional boolean array to be flattened.
* @return A one-dimensional boolean array containing all elements in the input array.
* Returns an empty array if the input array is {@code null} or empty.
*/
public static boolean[] flatten(final boolean[][] a) {
if (isEmpty(a)) {
return EMPTY_BOOLEAN_ARRAY;
}
int count = 0;
for (final boolean[] element : a) {
count += (element == null ? 0 : element.length);
}
final boolean[] ret = new boolean[count];
int from = 0;
for (final boolean[] element : a) {
if (notEmpty(element)) {
copy(element, 0, ret, from, element.length);
from += element.length;
}
}
return ret;
}
/**
* Flattens a two-dimensional char array into a one-dimensional char array.
*
* @param a The two-dimensional char array to be flattened.
* @return A one-dimensional char array containing all elements in the input array.
* Returns an empty array if the input array is {@code null} or empty.
*/
public static char[] flatten(final char[][] a) {
if (isEmpty(a)) {
return EMPTY_CHAR_ARRAY;
}
int count = 0;
for (final char[] element : a) {
count += (element == null ? 0 : element.length);
}
final char[] ret = new char[count];
int from = 0;
for (final char[] element : a) {
if (notEmpty(element)) {
copy(element, 0, ret, from, element.length);
from += element.length;
}
}
return ret;
}
/**
* Flattens a two-dimensional byte array into a one-dimensional byte array.
*
* @param a The two-dimensional byte array to be flattened.
* @return A one-dimensional byte array containing all elements in the input array.
* Returns an empty array if the input array is {@code null} or empty.
*/
public static byte[] flatten(final byte[][] a) {
if (isEmpty(a)) {
return EMPTY_BYTE_ARRAY;
}
int count = 0;
for (final byte[] element : a) {
count += (element == null ? 0 : element.length);
}
final byte[] ret = new byte[count];
int from = 0;
for (final byte[] element : a) {
if (notEmpty(element)) {
copy(element, 0, ret, from, element.length);
from += element.length;
}
}
return ret;
}
/**
* Flattens a two-dimensional short array into a one-dimensional short array.
*
* @param a The two-dimensional short array to be flattened.
* @return A one-dimensional short array containing all elements in the input array.
* Returns an empty array if the input array is {@code null} or empty.
*/
public static short[] flatten(final short[][] a) {
if (isEmpty(a)) {
return EMPTY_SHORT_ARRAY;
}
int count = 0;
for (final short[] element : a) {
count += (element == null ? 0 : element.length);
}
final short[] ret = new short[count];
int from = 0;
for (final short[] element : a) {
if (notEmpty(element)) {
copy(element, 0, ret, from, element.length);
from += element.length;
}
}
return ret;
}
/**
* Flattens a two-dimensional int array into a one-dimensional int array.
*
* @param a The two-dimensional int array to be flattened.
* @return A one-dimensional int array containing all elements in the input array.
* Returns an empty array if the input array is {@code null} or empty.
*/
public static int[] flatten(final int[][] a) {
if (isEmpty(a)) {
return EMPTY_INT_ARRAY;
}
int count = 0;
for (final int[] element : a) {
count += (element == null ? 0 : element.length);
}
final int[] ret = new int[count];
int from = 0;
for (final int[] element : a) {
if (notEmpty(element)) {
copy(element, 0, ret, from, element.length);
from += element.length;
}
}
return ret;
}
/**
* Flattens a two-dimensional long array into a one-dimensional long array.
*
* @param a The two-dimensional long array to be flattened.
* @return A one-dimensional long array containing all elements in the input array.
* Returns an empty array if the input array is {@code null} or empty.
*/
public static long[] flatten(final long[][] a) {
if (isEmpty(a)) {
return EMPTY_LONG_ARRAY;
}
int count = 0;
for (final long[] element : a) {
count += (element == null ? 0 : element.length);
}
final long[] ret = new long[count];
int from = 0;
for (final long[] element : a) {
if (notEmpty(element)) {
copy(element, 0, ret, from, element.length);
from += element.length;
}
}
return ret;
}
/**
* Flattens a two-dimensional float array into a one-dimensional float array.
*
* @param a The two-dimensional float array to be flattened.
* @return A one-dimensional float array containing all elements in the input array.
* Returns an empty array if the input array is {@code null} or empty.
*/
public static float[] flatten(final float[][] a) {
if (isEmpty(a)) {
return EMPTY_FLOAT_ARRAY;
}
int count = 0;
for (final float[] element : a) {
count += (element == null ? 0 : element.length);
}
final float[] ret = new float[count];
int from = 0;
for (final float[] element : a) {
if (notEmpty(element)) {
copy(element, 0, ret, from, element.length);
from += element.length;
}
}
return ret;
}
/**
* Flattens a two-dimensional double array into a one-dimensional double array.
*
* @param a The two-dimensional double array to be flattened.
* @return A one-dimensional double array containing all elements in the input array.
* Returns an empty array if the input array is {@code null} or empty.
*/
public static double[] flatten(final double[][] a) {
if (isEmpty(a)) {
return EMPTY_DOUBLE_ARRAY;
}
int count = 0;
for (final double[] element : a) {
count += (element == null ? 0 : element.length);
}
final double[] ret = new double[count];
int from = 0;
for (final double[] element : a) {
if (notEmpty(element)) {
copy(element, 0, ret, from, element.length);
from += element.length;
}
}
return ret;
}
/**
* Flattens a two-dimensional array into a one-dimensional array.
*
* @param The type of the elements in the array.
* @param a The two-dimensional array to be flattened.
* @return A one-dimensional array containing all elements in the input array. Returns {@code null} if the input array is {@code null}.
*/
@MayReturnNull
public static T[] flatten(final T[][] a) {
if (a == null) {
return null; // NOSONAR
}
return flatten(a, (Class) a.getClass().getComponentType().getComponentType());
}
/**
* Flattens a two-dimensional array into a one-dimensional array.
*
* @param The type of the elements in the array.
* @param a The two-dimensional array to be flattened.
* @param componentType The class object representing the component type of the new array.
* @return A one-dimensional array containing all elements in the input array.
* Returns an empty array if the input array is {@code null}.
*/
public static T[] flatten(final T[][] a, final Class componentType) {
if (isEmpty(a)) {
return newArray(componentType, 0);
}
int count = 0;
for (final T[] element : a) {
count += (element == null ? 0 : element.length);
}
final T[] ret = newArray(componentType, count);
int from = 0;
for (final T[] element : a) {
if (notEmpty(element)) {
copy(element, 0, ret, from, element.length);
from += element.length;
}
}
return ret;
}
// /**
// *
// * @param
// * @param c
// * @return
// */
// public static List flatten(final Collection extends Iterable extends T>> c) {
// return flatten(c, IntFunctions.ofList());
// }
//
// /**
// *
// *
// * @param
// * @param
// * @param c
// * @param supplier
// * @return
// */
// @SuppressWarnings("rawtypes")
// public static > C flatten(final Collection extends Iterable extends T>> c, IntFunction extends C> supplier) {
// if (isEmpty(c)) {
// return supplier.apply(0);
// }
//
// int count = 0;
//
// for (Iterable extends T> e : c) {
// count += e instanceof Collection ? ((Collection) e).size() : 3; //NOSONAR
// }
//
// final C ret = supplier.apply(count);
//
// for (Iterable extends T> e : c) {
// if (e == null) {
// continue; //NOSONAR
// } else if (e instanceof Collection) {
// ret.addAll((Collection) e);
// } else {
// for (T ee : e) {
// ret.add(ee);
// }
// }
// }
//
// return ret;
// }
/**
* Flattens an {@code Iterable} of {@code Iterable} into a one-dimensional List.
*
* @param The type of the elements in the {@code Iterable}.
* @param c The two-dimensional {@code Iterable} to be flattened.
* @return A one-dimensional List containing all elements in the input {@code Iterable}.
* Returns an empty List if the input {@code Iterable} is {@code null} or empty.
*/
public static List flatten(final Iterable extends Iterable extends T>> c) {
return flatten(c, Factory.ofList());
}
/**
* Flattens an {@code Iterable} of {@code Iterable} into a one-dimensional Collection.
*
* @param The type of the elements in the {@code Iterable}.
* @param The type of the Collection to be returned.
* @param c The two-dimensional {@code Iterable} to be flattened.
* @param supplier The function that generates the Collection instance.
* @return A one-dimensional Collection containing all elements in the input {@code Iterable}.
* Returns an empty Collection if the input {@code Iterable} is {@code null} or empty.
*/
@SuppressWarnings("rawtypes")
public static > C flatten(final Iterable extends Iterable extends T>> c, final IntFunction extends C> supplier) {
if (isEmpty(c)) {
return supplier.apply(0);
}
int count = 0;
for (final Iterable extends T> e : c) {
count += e instanceof Collection ? ((Collection) e).size() : DEFAULT_SIZE_FOR_NEW_COLLECTION; //NOSONAR
}
final C ret = supplier.apply(count);
for (final Iterable extends T> e : c) {
if (e == null) {
//NOSONAR
} else if (e instanceof Collection) {
ret.addAll((Collection) e);
} else {
for (final T ee : e) {
ret.add(ee);
}
}
}
return ret;
}
/**
* Flattens an {@code Iterator} of {@code Iterator} into a one-dimensional Iterator.
*
* @param The type of the elements in the Iterator.
* @param iters The two-dimensional Iterator to be flattened.
* @return A one-dimensional Iterator containing all elements in the input {@code Iterator}.
* Returns an empty Iterator if the input {@code Iterator} is {@code null}.
*/
public static ObjIterator flatten(final Iterator extends Iterator extends T>> iters) {
if (iters == null) {
return ObjIterator.empty();
}
return new ObjIterator<>() {
private Iterator extends T> cur = null;
@Override
public boolean hasNext() {
if (cur == null || !cur.hasNext()) {
while (iters.hasNext()) {
cur = iters.next();
if (cur != null && cur.hasNext()) {
break;
}
}
}
return cur != null && cur.hasNext();
}
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
return cur.next();
}
};
}
/**
* Flattens each element of the provided {@code Iterable} if it's an {@code Iterable} itself, otherwise just adds it to the result List.
* This method is marked as Beta and may be subject to changes or removal in future versions.
*
* @param c The {@code Iterable} to be processed. Each element is checked if it's an {@code Iterable} and flattened if so.
* @return A List containing the flattened elements of the input {@code Iterable}. If the input {@code Iterable} is {@code null}, an empty List is returned.
*/
@Beta
public static List> flattenEachElement(final Iterable> c) { //NOSONAR
return flattenEachElement(c, Suppliers.ofList());
}
/**
* Flattens each element of the provided {@code Iterable} if it's an {@code Iterable} itself, otherwise just adds it to the result Collection.
* This method is marked as Beta and may be subject to changes or removal in future versions.
*
* @param The type of the elements in the {@code Iterable}.
* @param The type of the Collection to be returned.
* @param c The {@code Iterable} to be processed. Each element is checked if it's an {@code Iterable} and flattened if so.
* @param supplier The function that generates the Collection instance.
* @return A Collection containing the flattened elements of the input {@code Iterable}. If the input {@code Iterable} is {@code null}, an empty Collection is returned.
*/
@Beta
public static > C flattenEachElement(final Iterable> c, final Supplier extends C> supplier) {
if (isEmptyCollection(c)) {
return supplier.get();
}
final C result = supplier.get();
flattenEachElement((Iterable) c, (Collection) result);
return result;
}
private static void flattenEachElement(final Iterable c, final Collection output) {
for (final Object next : c) {
if (next instanceof Iterable) {
flattenEachElement((Iterable) next, output);
} else {
output.add(next);
}
}
}
/**
* Returns the elements in the specified boolean arrays a and b that are present in both arrays.
* Occurrences are considered.
*
* @param a The first boolean array.
* @param b The second boolean array.
* @return A new boolean array containing the elements that are present in both a and b .
* If either a or b is empty or {@code null}, an empty array is returned.
* @see #intersection(int[], int[])
*/
public static boolean[] intersection(final boolean[] a, final boolean[] b) {
if (isEmpty(a) || isEmpty(b)) {
return isEmpty(a) ? a : EMPTY_BOOLEAN_ARRAY;
}
return BooleanList.of(a).intersection(BooleanList.of(b)).trimToSize().array();
}
/**
* Returns the elements in the specified char arrays a and b that are present in both arrays.
* Occurrences are considered.
*
* @param a The first char array.
* @param b The second char array.
* @return A new char array containing the elements that are present in both a and b .
* If either a or b is empty or {@code null}, an empty array is returned.
* @see #intersection(int[], int[])
*/
public static char[] intersection(final char[] a, final char[] b) {
if (isEmpty(a) || isEmpty(b)) {
return EMPTY_CHAR_ARRAY;
}
return CharList.of(a).intersection(CharList.of(b)).trimToSize().array();
}
/**
* Returns the elements in the specified byte arrays a and b that are present in both arrays.
* Occurrences are considered.
*
* @param a The first byte array.
* @param b The second byte array.
* @return A new byte array containing the elements that are present in both a and b .
* If either a or b is empty or {@code null}, an empty array is returned.
* @see #intersection(int[], int[])
*/
public static byte[] intersection(final byte[] a, final byte[] b) {
if (isEmpty(a) || isEmpty(b)) {
return EMPTY_BYTE_ARRAY;
}
return ByteList.of(a).intersection(ByteList.of(b)).trimToSize().array();
}
/**
* Returns the elements in the specified short arrays a and b that are present in both arrays.
* Occurrences are considered.
*
* @param a The first short array.
* @param b The second short array.
* @return A new short array containing the elements that are present in both a and b .
* If either a or b is empty or {@code null}, an empty array is returned.
* @see #intersection(int[], int[])
*/
public static short[] intersection(final short[] a, final short[] b) {
if (isEmpty(a) || isEmpty(b)) {
return EMPTY_SHORT_ARRAY;
}
return ShortList.of(a).intersection(ShortList.of(b)).trimToSize().array();
}
/**
* Returns the elements in the specified int arrays a and b that are present in both arrays.
* Occurrences are considered.
*
*
* int[] a = {0, 1, 2, 2, 3};
* int[] b = {2, 5, 1};
* int[] c = retainAll(a, b); // The elements c in a will b: [1, 2, 2].
*
* int[] a = {0, 1, 2, 2, 3};
* int[] b = {2, 5, 1};
* int[] c = intersection(a, b); // The elements c in a will b: [1, 2].
*
*
* @param a The first int array.
* @param b The second int array.
* @return A new int array containing the elements that are present in both a and b .
* If either a or b is empty or {@code null}, an empty array is returned.
*/
public static int[] intersection(final int[] a, final int[] b) {
if (isEmpty(a) || isEmpty(b)) {
return EMPTY_INT_ARRAY;
}
return IntList.of(a).intersection(IntList.of(b)).trimToSize().array();
}
/**
* Returns the elements in the specified long arrays a and b that are present in both arrays.
* Occurrences are considered.
*
* @param a The first long array.
* @param b The second long array.
* @return A new long array containing the elements that are present in both a and b .
* If either a or b is empty or {@code null}, an empty array is returned.
* @see #intersection(int[], int[])
*/
public static long[] intersection(final long[] a, final long[] b) {
if (isEmpty(a) || isEmpty(b)) {
return EMPTY_LONG_ARRAY;
}
return LongList.of(a).intersection(LongList.of(b)).trimToSize().array();
}
/**
* Returns the elements in the specified float arrays a and b that are present in both arrays.
* Occurrences are considered.
*
* @param a The first float array.
* @param b The second float array.
* @return A new float array containing the elements that are present in both a and b .
* If either a or b is empty or {@code null}, an empty array is returned.
* @see #intersection(int[], int[])
*/
public static float[] intersection(final float[] a, final float[] b) {
if (isEmpty(a) || isEmpty(b)) {
return EMPTY_FLOAT_ARRAY;
}
return FloatList.of(a).intersection(FloatList.of(b)).trimToSize().array();
}
/**
* Returns the elements in the specified double arrays a and b that are present in both arrays.
* Occurrences are considered.
*
* @param a The first double array.
* @param b The second double array.
* @return A new double array containing the elements that are present in both a and b .
* If either a or b is empty or {@code null}, an empty array is returned.
* @see #intersection(int[], int[])
*/
public static double[] intersection(final double[] a, final double[] b) {
if (isEmpty(a) || isEmpty(b)) {
return EMPTY_DOUBLE_ARRAY;
}
return DoubleList.of(a).intersection(DoubleList.of(b)).trimToSize().array();
}
/**
* Returns the elements in the specified arrays a and b that are present in both arrays.
* Occurrences are considered.
*
* @param The type of the elements in the input array.
* @param a The first array.
* @param b The second array.
* @return A new list containing the elements that are present in both a and b .
* If either a or b is empty or {@code null}, an empty list is returned.
* @see #intersection(int[], int[])
* @see #intersection(Collection, Collection, boolean)
* @see #commonSet(Collection, Collection)
* @see Collection#retainAll(Collection)
* @see Iterables#intersection(Set, Set)
*/
public static List intersection(final T[] a, final Object[] b) {
if (isEmpty(a) || isEmpty(b)) {
return new ArrayList<>();
}
final Multiset> bOccurrences = Multiset.of(b);
final List result = new ArrayList<>(min(9, a.length, b.length));
for (final T e : a) {
if (bOccurrences.remove(e)) {
result.add(e);
}
}
return result;
}
/**
* Returns the elements in the specified collections a and b that are present in both collections.
* Occurrences are considered.
*
* @param the type of elements in the input collections
* @param a the first collection
* @param b the second collection
* @return a list containing the elements that are present in both collections
* If either a or b is empty or {@code null}, an empty list is returned.
* @see #intersection(int[], int[])
* @see #intersection(Collection, Collection, boolean)
* @see #commonSet(Collection, Collection)
* @see Collection#retainAll(Collection)
* @see Iterables#intersection(Set, Set)
*/
public static List intersection(final Collection extends T> a, final Collection> b) {
if (isEmpty(a) || isEmpty(b)) {
return new ArrayList<>();
}
final Multiset bOccurrences = Multiset.create(b);
final List result = new ArrayList<>(min(9, a.size(), b.size()));
for (final T e : a) {
if (bOccurrences.remove(e)) {
result.add(e);
}
}
return result;
}
/**
* Returns the elements that are present in all collections within the specified collection of collections.
* Occurrences are considered.
*
* @param The type of the elements in the collections.
* @param c The collection of collections to find the intersection of.
* @return A list containing the elements that are present in all collections within c .
* If c is empty or {@code null}, an empty list is returned.
* If c contains only one collection, a list containing the elements of this collection is returned.
* @see #intersection(int[], int[])
* @see #intersection(Collection, Collection, boolean)
* @see #commonSet(Collection, Collection)
* @see Collection#retainAll(Collection)
* @see Iterables#intersection(Set, Set)
*/
public static List intersection(final Collection extends Collection extends T>> c) {
if (isEmpty(c)) {
return new ArrayList<>();
} else if (c.size() == 1) {
return newArrayList(c.iterator().next());
}
for (final Collection extends T> e : c) {
if (isEmpty(e)) {
return new ArrayList<>();
}
}
final Iterator extends Collection extends T>> iter = c.iterator();
List result = intersection(iter.next(), iter.next());
while (iter.hasNext()) {
result = intersection(result, iter.next());
if (result.size() == 0) {
break;
}
}
return result;
}
/**
* Return only the elements in the first collection that are contained in the specified second collection.
*
* If {@code ignoreOccurrences} is {@code true}, Occurrences are not considered.
*
* Duplicated elements in the returned List will not be eliminated.
*
* List a = N.asList(0, 1, 2, 2, 3);
* List b = N.asList(2, 5, 1);
* List c = N.intersection(a, b, false); // The elements c in a will b: [1, 2]. same as N.intersection(a, b).
* List d = N.intersection(a, b, true); // The elements c in a will b: [1, 2, 2].
*
*
* @param the type of elements in the input collections
* @param a the first collection, elements from this collection will be retained
* @param b the second collection, elements in this collection are to be retained in the first collection
* @param ignoreOccurrences if {@code true}, the method does not consider the number of occurrences of an element.
* @return a List the elements in the first collection that are contained in the specified second collection.
* @see #intersection(Collection, Collection)
* @see #commonSet(Collection, Collection)
* @see Iterables#intersection(Set, Set)
* @see Collection#retainAll(Collection)
*/
@Beta
public static List intersection(final Collection extends T> a, final Collection> b, final boolean ignoreOccurrences) {
if (isEmpty(a) || isEmpty(b)) {
return newArrayList();
}
if (!ignoreOccurrences) {
return intersection(a, b);
}
final Set set = b instanceof Set ? (Set) b : (Set) newHashSet(b);
final List result = new ArrayList<>(max(0, a.size() - b.size()));
for (final T e : a) {
if (set.contains(e)) {
result.add(e);
}
}
return result;
}
/**
* Returns the elements in the specified boolean array a but not present in the boolean array b .
* Occurrences are considered.
*
* @param a The first boolean array.
* @param b The second boolean array.
* @return A new boolean array containing the elements that are present in a but not in b .
* If a is empty or {@code null}, an empty array is returned.
* If b is empty or {@code null}, a clone of a is returned.
* @see #difference(int[], int[])
*/
public static boolean[] difference(final boolean[] a, final boolean[] b) {
if (isEmpty(a)) {
return EMPTY_BOOLEAN_ARRAY;
} else if (isEmpty(b)) {
return a.clone();
}
return BooleanList.of(a).difference(BooleanList.of(b)).trimToSize().array();
}
/**
* Returns the elements in the specified char array a but not present in the char array b .
* Occurrences are considered.
*
* @param a The first char array.
* @param b The second char array.
* @return A new char array containing the elements that are present in a but not in b .
* If a is empty or {@code null}, an empty array is returned.
* If b is empty or {@code null}, a clone of a is returned
* @see #difference(int[], int[])
*/
public static char[] difference(final char[] a, final char[] b) {
if (isEmpty(a)) {
return EMPTY_CHAR_ARRAY;
} else if (isEmpty(b)) {
return a.clone();
}
return CharList.of(a).difference(CharList.of(b)).trimToSize().array();
}
/**
* Returns the elements in the specified byte array a but not present in the byte array b .
* Occurrences are considered.
*
* @param a The first byte array.
* @param b The second byte array.
* @return A new byte array containing the elements that are present in a but not in b .
* If a is empty or {@code null}, an empty array is returned.
* If b is empty or {@code null}, a clone of a is returned
* @see #difference(int[], int[])
*/
public static byte[] difference(final byte[] a, final byte[] b) {
if (isEmpty(a)) {
return EMPTY_BYTE_ARRAY;
} else if (isEmpty(b)) {
return a.clone();
}
return ByteList.of(a).difference(ByteList.of(b)).trimToSize().array();
}
/**
* Returns the elements in the specified short array a but not present in the short array b .
* Occurrences are considered.
*
* @param a The first short array.
* @param b The second short array.
* @return A new short array containing the elements that are present in a but not in b .
* If a is empty or {@code null}, an empty array is returned.
* If b is empty or {@code null}, a clone of a is returned
* @see #difference(int[], int[])
*/
public static short[] difference(final short[] a, final short[] b) {
if (isEmpty(a)) {
return EMPTY_SHORT_ARRAY;
} else if (isEmpty(b)) {
return a.clone();
}
return ShortList.of(a).difference(ShortList.of(b)).trimToSize().array();
}
/**
* Returns the elements in the specified int array a but not present in the int array b .
* Occurrences are considered.
*
*
* int[] a = {0, 1, 2, 2, 3};
* int[] b = {2, 5, 1};
* int[] c = removeAll(a, b); // The elements c in a will b: [0, 3].
*
* int[] a = {0, 1, 2, 2, 3};
* int[] b = {2, 5, 1};
* int[] c = difference(a, b); // The elements c in a will b: [0, 2, 3].
*
*
* @param a The first int array.
* @param b The second int array.
* @return A new int array containing the elements that are present in a but not in b .
* If a is empty or {@code null}, an empty array is returned.
* If b is empty or {@code null}, a clone of a is returned
*/
public static int[] difference(final int[] a, final int[] b) {
if (isEmpty(a)) {
return EMPTY_INT_ARRAY;
} else if (isEmpty(b)) {
return a.clone();
}
return IntList.of(a).difference(IntList.of(b)).trimToSize().array();
}
/**
* Returns the elements in the specified long array a but not present in the long array b .
* Occurrences are considered.
*
* @param a The first long array.
* @param b The second long array.
* @return A new long array containing the elements that are present in a but not in b .
* If a is empty or {@code null}, an empty array is returned.
* If b is empty or {@code null}, a clone of a is returned
* @see #difference(int[], int[])
*/
public static long[] difference(final long[] a, final long[] b) {
if (isEmpty(a)) {
return EMPTY_LONG_ARRAY;
} else if (isEmpty(b)) {
return a.clone();
}
return LongList.of(a).difference(LongList.of(b)).trimToSize().array();
}
/**
* Returns the elements in the specified float array a but not present in the float array b .
* Occurrences are considered.
*
* @param a The first float array.
* @param b The second float array.
* @return A new float array containing the elements that are present in a but not in b .
* If a is empty or {@code null}, an empty array is returned.
* If b is empty or {@code null}, a clone of a is returned
* @see #difference(int[], int[])
*/
public static float[] difference(final float[] a, final float[] b) {
if (isEmpty(a)) {
return EMPTY_FLOAT_ARRAY;
} else if (isEmpty(b)) {
return a.clone();
}
return FloatList.of(a).difference(FloatList.of(b)).trimToSize().array();
}
/**
* Returns the elements in the specified double array a but not present in the double array b .
* Occurrences are considered.
*
* @param a The first double array.
* @param b The second double array.
* @return A new double array containing the elements that are present in a but not in b .
* If a is empty or {@code null}, an empty array is returned.
* If b is empty or {@code null}, a clone of a is returned
* @see #difference(int[], int[])
*/
public static double[] difference(final double[] a, final double[] b) {
if (isEmpty(a)) {
return EMPTY_DOUBLE_ARRAY;
} else if (isEmpty(b)) {
return a.clone();
}
return DoubleList.of(a).difference(DoubleList.of(b)).trimToSize().array();
}
/**
* Returns the elements in the specified arrays a but not present in the specified array b .
* Occurrences are considered.
*
* @param The type of the elements in the input array.
* @param a The first array.
* @param b The second array.
* @return A new list containing the elements that are present in a but not in b .
* If a is empty or {@code null}, an empty list is returned.
* If b is empty or {@code null}, a clone of a is returned
* @see #difference(int[], int[])
* @see #excludeAll(Collection, Collection)
* @see #excludeAllToSet(Collection, Collection)
* @see #removeAll(Collection, Iterable)
* @see Iterables#difference(Set, Set)
* @see Difference#of(Collection, Collection
*/
public static List difference(final T[] a, final Object[] b) {
if (isEmpty(a)) {
return new ArrayList<>();
} else if (isEmpty(b)) {
return asList(a);
}
final Multiset> bOccurrences = Multiset.of(b);
final List result = new ArrayList<>(min(a.length, max(9, a.length - b.length)));
for (final T e : a) {
if (!bOccurrences.remove(e)) {
result.add(e);
}
}
return result;
}
/**
* Returns the elements in the specified collections a but not present in the specified collection b .
* Occurrences are considered.
*
* @param The type of the elements in the collections.
* @param a The first collection.
* @param b The second collection.
* @return A new list containing the elements that are present in a but not in b .
* If a is empty or {@code null}, an empty list is returned.
* If b is empty or {@code null}, a new list with all element from a is returned
* @see #difference(int[], int[])
* @see #excludeAll(Collection, Collection)
* @see #excludeAllToSet(Collection, Collection)
* @see #removeAll(Collection, Iterable)
* @see Iterables#difference(Set, Set)
* @see Difference#of(Collection, Collection
*/
public static List difference(final Collection extends T> a, final Collection> b) {
if (isEmpty(a)) {
return new ArrayList<>();
} else if (isEmpty(b)) {
return new ArrayList<>(a);
}
final Multiset bOccurrences = Multiset.create(b);
final List result = new ArrayList<>(min(a.size(), max(9, a.size() - b.size())));
for (final T e : a) {
if (!bOccurrences.remove(e)) {
result.add(e);
}
}
return result;
}
/**
* Returns the elements that are present in either a or b but not in both.
* Occurrences are considered.
*
* @param a The first boolean array.
* @param b The second boolean array.
* @return A new boolean array containing the elements that are present in either a or b but not in both.
* If both a and b are empty or {@code null}, an empty array is returned.
* If a is empty or {@code null}, a clone of b is returned.
* If b is empty or {@code null}, a clone of a is returned.
* @see #symmetricDifference(int[], int[])
*/
public static boolean[] symmetricDifference(final boolean[] a, final boolean[] b) {
if (isEmpty(a)) {
return isEmpty(b) ? EMPTY_BOOLEAN_ARRAY : b.clone();
} else if (isEmpty(b)) {
return a.clone();
}
return BooleanList.of(a).symmetricDifference(BooleanList.of(b)).trimToSize().array();
}
/**
* Returns the elements that are present in either a or b but not in both.
* Occurrences are considered.
*
* @param a The first char array.
* @param b The second char array.
* @return A new char array containing the elements that are present in either a or b but not in both.
* If both a and b are empty or {@code null}, an empty array is returned.
* If a is empty or {@code null}, a clone of b is returned.
* If b is empty or {@code null}, a clone of a is returned.
* @see #symmetricDifference(int[], int[])
*/
public static char[] symmetricDifference(final char[] a, final char[] b) {
if (isEmpty(a)) {
return isEmpty(b) ? EMPTY_CHAR_ARRAY : b.clone();
} else if (isEmpty(b)) {
return a.clone();
}
return CharList.of(a).symmetricDifference(CharList.of(b)).trimToSize().array();
}
/**
* Returns the elements that are present in either a or b but not in both.
* Occurrences are considered.
*
* @param a The first byte array.
* @param b The second byte array.
* @return A new byte array containing the elements that are present in either a or b but not in both.
* If both a and b are empty or {@code null}, an empty array is returned.
* If a is empty or {@code null}, a clone of b is returned.
* If b is empty or {@code null}, a clone of a is returned.
* @see #symmetricDifference(int[], int[])
*/
public static byte[] symmetricDifference(final byte[] a, final byte[] b) {
if (isEmpty(a)) {
return isEmpty(b) ? EMPTY_BYTE_ARRAY : b.clone();
} else if (isEmpty(b)) {
return a.clone();
}
return ByteList.of(a).symmetricDifference(ByteList.of(b)).trimToSize().array();
}
/**
* Returns the elements that are present in either a or b but not in both.
* Occurrences are considered.
*
* @param a The first short array.
* @param b The second short array.
* @return A new short array containing the elements that are present in either a or b but not in both.
* If both a and b are empty or {@code null}, an empty array is returned.
* If a is empty or {@code null}, a clone of b is returned.
* If b is empty or {@code null}, a clone of a is returned.
* @see #symmetricDifference(int[], int[])
*/
public static short[] symmetricDifference(final short[] a, final short[] b) {
if (isEmpty(a)) {
return isEmpty(b) ? EMPTY_SHORT_ARRAY : b.clone();
} else if (isEmpty(b)) {
return a.clone();
}
return ShortList.of(a).symmetricDifference(ShortList.of(b)).trimToSize().array();
}
/**
* Returns the elements that are present in either a or b but not in both.
* Occurrences are considered.
*
*
* int[] a = {0, 1, 2, 2, 3};
* int[] b = {2, 5, 1};
* int[] c = symmetricDifference(a, b); // The elements c in a will b: [0, 2, 3, 5].
*
*
* @param a The first int array.
* @param b The second int array.
* @return A new int array containing the elements that are present in either a or b but not in both.
* If both a and b are empty or {@code null}, an empty array is returned.
* If a is empty or {@code null}, a clone of b is returned.
* If b is empty or {@code null}, a clone of a is returned.
* @see #symmetricDifference(int[], int[])
*/
public static int[] symmetricDifference(final int[] a, final int[] b) {
if (isEmpty(a)) {
return isEmpty(b) ? EMPTY_INT_ARRAY : b.clone();
} else if (isEmpty(b)) {
return a.clone();
}
return IntList.of(a).symmetricDifference(IntList.of(b)).trimToSize().array();
}
/**
* Returns the elements that are present in either a or b but not in both.
* Occurrences are considered.
*
* @param a The first long array.
* @param b The second long array.
* @return A new long array containing the elements that are present in either a or b but not in both.
* If both a and b are empty or {@code null}, an empty array is returned.
* If a is empty or {@code null}, a clone of b is returned.
* If b is empty or {@code null}, a clone of a is returned.
* @see #symmetricDifference(int[], int[])
*/
public static long[] symmetricDifference(final long[] a, final long[] b) {
if (isEmpty(a)) {
return isEmpty(b) ? EMPTY_LONG_ARRAY : b.clone();
} else if (isEmpty(b)) {
return a.clone();
}
return LongList.of(a).symmetricDifference(LongList.of(b)).trimToSize().array();
}
/**
* Returns the elements that are present in either a or b but not in both.
* Occurrences are considered.
*
* @param a The first float array.
* @param b The second float array.
* @return A new float array containing the elements that are present in either a or b but not in both.
* If both a and b are empty or {@code null}, an empty array is returned.
* If a is empty or {@code null}, a clone of b is returned.
* If b is empty or {@code null}, a clone of a is returned.
* @see #symmetricDifference(int[], int[])
*/
public static float[] symmetricDifference(final float[] a, final float[] b) {
if (isEmpty(a)) {
return isEmpty(b) ? EMPTY_FLOAT_ARRAY : b.clone();
} else if (isEmpty(b)) {
return a.clone();
}
return FloatList.of(a).symmetricDifference(FloatList.of(b)).trimToSize().array();
}
/**
* Returns the elements that are present in either a or b but not in both.
* Occurrences are considered.
*
* @param a The first double array.
* @param b The second double array.
* @return A new double array containing the elements that are present in either a or b but not in both.
* If both a and b are empty or {@code null}, an empty array is returned.
* If a is empty or {@code null}, a clone of b is returned.
* If b is empty or {@code null}, a clone of a is returned.
* @see #symmetricDifference(int[], int[])
*/
public static double[] symmetricDifference(final double[] a, final double[] b) {
if (isEmpty(a)) {
return isEmpty(b) ? EMPTY_DOUBLE_ARRAY : b.clone();
} else if (isEmpty(b)) {
return a.clone();
}
return DoubleList.of(a).symmetricDifference(DoubleList.of(b)).trimToSize().array();
}
/**
* Returns the elements that are present in either a or b but not in both.
* Occurrences are considered.
*
* @param The type of the elements in the arrays.
* @param a The first array.
* @param b The second array.
* @return A new list containing the elements that are present in either a or b but not in both.
* If both a and b are empty or {@code null}, an empty list is returned.
* If a is empty or {@code null}, a list containing the elements of b is returned.
* If b is empty or {@code null}, a list containing the elements of a is returned.
* @see #symmetricDifference(int[], int[])
* @see #excludeAll(Collection, Collection)
* @see #excludeAllToSet(Collection, Collection)
* @see #difference(Collection, Collection)
* @see Difference#of(Collection, Collection)
* @see Iterables#symmetricDifference(Set, Set)
*/
public static List symmetricDifference(final T[] a, final T[] b) {
if (isEmpty(a)) {
return asList(b);
} else if (isEmpty(b)) {
return asList(a);
}
final Multiset bOccurrences = Multiset.of(b);
final List result = new ArrayList<>(max(9, Math.abs(a.length - b.length)));
for (final T e : a) {
if (!bOccurrences.remove(e)) {
result.add(e);
}
}
for (final T e : b) {
if (bOccurrences.remove(e)) {
result.add(e);
}
if (bOccurrences.isEmpty()) {
break;
}
}
return result;
}
/**
* Returns the elements that are present in either a or b but not in both.
* Occurrences are considered.
*
* @param The type of the elements in the collections.
* @param a The first collection.
* @param b The second collection.
* @return A new list containing the elements that are present in either a or b but not in both.
* If both a and b are empty or {@code null}, an empty list is returned.
* If a is empty or {@code null}, a list containing the elements of b is returned.
* If b is empty or {@code null}, a list containing the elements of a is returned.
* @see #symmetricDifference(int[], int[])
* @see #excludeAll(Collection, Collection)
* @see #excludeAllToSet(Collection, Collection)
* @see #difference(Collection, Collection)
* @see Difference#of(Collection, Collection)
* @see Iterables#symmetricDifference(Set, Set)
*/
public static List symmetricDifference(final Collection extends T> a, final Collection extends T> b) {
if (isEmpty(a)) {
return isEmpty(b) ? new ArrayList<>() : new ArrayList<>(b);
} else if (isEmpty(b)) {
return isEmpty(a) ? new ArrayList<>() : new ArrayList<>(a);
}
final Multiset bOccurrences = Multiset.create(b);
final List result = new ArrayList<>(max(9, Math.abs(a.size() - b.size())));
for (final T e : a) {
if (!bOccurrences.remove(e)) {
result.add(e);
}
}
for (final T e : b) {
if (bOccurrences.remove(e)) {
result.add(e);
}
if (bOccurrences.isEmpty()) {
break;
}
}
return result;
}
// /**
// * Returns a set containing elements that are in the first collection a but not in the second collection b .
// * The returned set does not contain duplicate elements.
// *
// * @param the type of elements in the input collections
// * @param a the first collection to be compared
// * @param b the second collection to be compared
// * @return a Set containing the difference of the two collections
// * @see #difference(Collection, Collection)
// * @see #excludeAll(Collection, Collection)
// * @see #excludeAllToSet(Collection, Collection)
// * @see #removeAll(Collection, Iterable)
// * @see Iterables#difference(Set, Set)
// * @see Difference#of(Collection, Collection)
// */
// @SuppressWarnings("rawtypes")
// public static Set differentSet(final Collection extends T> a, final Collection> b) {
// if (isEmpty(a)) {
// return newHashSet();
// } else if (isEmpty(b)) {
// return newHashSet(a);
// }
//
// final Set result = a instanceof List || a instanceof LinkedHashSet ? newLinkedHashSet(a) : newHashSet(a);
//
// removeAll(result, (Collection) b);
//
// return result;
// }
// /**
// * Returns a Set containing elements that are in either of the input collections but not in both.
// * In other words, it returns a Set containing the symmetric difference of the two input collections.
// * The returned Set does not contain duplicate elements.
// *
// * @param The type of elements in the collections.
// * @param a The first collection to be compared.
// * @param b The second collection to be compared.
// * @return A Set containing the symmetric difference of the two collections.
// * @see #symmetricDifference(Collection, Collection)
// * @see #excludeAll(Collection, Collection)
// * @see #excludeAllToSet(Collection, Collection)
// * @see Iterables#symmetricDifference(Set, Set)
// * @see Difference#of(Collection, Collection)
// */
// public static Set symmetricDifferentSet(final Collection extends T> a, final Collection extends T> b) {
// if (isEmpty(a)) {
// return isEmpty(b) ? newHashSet() : newHashSet(b);
// } else if (isEmpty(b)) {
// return isEmpty(a) ? newHashSet() : newHashSet(a);
// }
//
// final Set commonSet = commonSet(a, b);
// final Set result = a instanceof List || a instanceof LinkedHashSet ? newLinkedHashSet() : newHashSet();
//
// for (final T e : a) {
// if (!commonSet.contains(e)) {
// result.add(e);
// }
// }
//
// for (final T e : b) {
// if (!commonSet.contains(e)) {
// result.add(e);
// }
// }
//
// return result;
// }
/**
* Returns a set containing the common elements between the specified collections a and b .
*
* @param The type of the elements in the collection a .
* @param a The first collection.
* @param b The second collection.
* @return A set containing the elements that are present in both a and b .
* If either a or b is empty or {@code null}, an empty set is returned.
* @see #intersection(Collection, Collection)
* @see #intersection(Collection, Collection, boolean)
* @see Collection#retainAll(Collection)
* @see Iterables#intersection(Set, Set)
*/
public static Set commonSet(final Collection extends T> a, final Collection> b) {
if (isEmpty(a) || isEmpty(b)) {
return newHashSet();
}
return commonSet(Array.asList(a, (Collection extends T>) b));
}
/**
* Returns a set containing the common elements among all the collections within the specified collection of collections.
*
* @param The type of the elements in the collections.
* @param c The collection of collections to find the common elements of.
* @return A set containing the elements that are present in all collections within c .
* If c is empty or {@code null}, an empty set is returned.
* If c contains only one collection, a set containing the elements of this collection is returned.
* @see #intersection(Collection, Collection)
* @see #intersection(Collection, Collection, boolean)
* @see Collection#retainAll(Collection)
* @see Iterables#intersection(Set, Set)
*/
public static Set commonSet(final Collection extends Collection extends T>> c) {
if (isEmpty(c)) {
return newHashSet();
} else if (c.size() == 1) {
return newHashSet(c.iterator().next());
}
Collection extends T> smallest = null;
for (final Collection extends T> e : c) {
if (isEmpty(e)) {
return newHashSet();
}
if (smallest == null || e.size() < smallest.size()) {
smallest = e;
}
}
final Map map = new HashMap<>();
//noinspection DataFlowIssue
for (final T e : smallest) {
map.put(e, new MutableInt(1));
}
int cnt = 1;
MutableInt val = null;
for (final Collection extends T> ec : c) {
if (ec == smallest) { // NOSONAR
continue;
}
for (final T e : ec) {
val = map.get(e);
if ((val == null) || (val.value() < cnt)) {
// do nothing.
} else if (val.value() == cnt) {
val.increment();
}
}
cnt++;
}
final Collection extends T> firstSet = N.firstOrNullIfEmpty(c);
final Set result = firstSet instanceof List || firstSet instanceof LinkedHashSet ? newLinkedHashSet(map.size()) : newHashSet(map.size());
for (final Map.Entry entry : map.entrySet()) {
if (entry.getValue().value() == cnt) {
result.add(entry.getKey());
}
}
return result;
}
/**
* Returns a new {@code List} containing all the elements from the specified collection except all occurrences of specified objToExclude .
*
* @param The type of the elements in the collection.
* @param c The collection from which to exclude the specified object.
* @param objToExclude The object to exclude from the collection.
* @return A new {@code List} with the specified object excluded.
* If the collection c is empty or {@code null}, an empty list is returned.
* @see #difference(Collection, Collection)
* @see #removeAll(Collection, Iterable)
* @see Difference#of(Collection, Collection)
*/
public static List exclude(final Collection extends T> c, final Object objToExclude) {
if (isEmpty(c)) {
return new ArrayList<>();
}
final List result = new ArrayList<>(c.size() - 1);
for (final T e : c) {
if (!equals(e, objToExclude)) {
result.add(e);
}
}
return result;
}
/**
* Returns a new {@code Set} containing all the elements from the specified collection except all occurrences of specified objToExclude .
*
* @param The type of the elements in the collection.
* @param c The collection from which to exclude the specified object.
* @param objToExclude The object to exclude from the collection.
* @return A new {@code Set} with the specified object excluded.
* If the collection c is empty or {@code null}, an empty set is returned.
* @see #difference(Collection, Collection)
* @see #removeAll(Collection, Iterable)
* @see Difference#of(Collection, Collection)
*/
public static Set excludeToSet(final Collection extends T> c, final Object objToExclude) {
if (isEmpty(c)) {
return new HashSet<>();
}
final Set result = c instanceof List || c instanceof LinkedHashSet ? newLinkedHashSet(c) : newHashSet(c);
//noinspection SuspiciousMethodCalls
result.remove(objToExclude);
return result;
}
/**
* Returns a new {@code List} containing all the elements from the specified collection except all occurrences of elements in the specified objsToExclude .
* That's to say no more value from objsToExclude will present in the returned {@code Set}.
*
* @param The type of the elements in the collection.
* @param c The collection from which to exclude the specified objects.
* @param objsToExclude The objects to exclude from the collection.
* @return A new {@code List} with the specified objects excluded.
* If the collection