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

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.

The newest version!
/*
 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 a, final Iterable 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... 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> 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> c, final IntFunction supplier) { if (isEmpty(c)) { return supplier.apply(0); } long count = 0; for (final Iterable e : c) { count += getSizeOrDefault(e, 0); } final C result = supplier.apply(Numbers.toIntExact(count)); for (final Iterable 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 a, final Iterator 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... 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> c) { // return flatten(c, IntFunctions.ofList()); // } // // /** // * // * // * @param // * @param // * @param c // * @param supplier // * @return // */ // @SuppressWarnings("rawtypes") // public static > C flatten(final Collection> c, IntFunction supplier) { // if (isEmpty(c)) { // return supplier.apply(0); // } // // int count = 0; // // for (Iterable e : c) { // count += e instanceof Collection ? ((Collection) e).size() : 3; //NOSONAR // } // // final C ret = supplier.apply(count); // // for (Iterable 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> 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> c, final IntFunction supplier) { if (isEmpty(c)) { return supplier.apply(0); } int count = 0; for (final Iterable e : c) { count += e instanceof Collection ? ((Collection) e).size() : DEFAULT_SIZE_FOR_NEW_COLLECTION; //NOSONAR } final C ret = supplier.apply(count); for (final Iterable 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> iters) { if (iters == null) { return ObjIterator.empty(); } return new ObjIterator<>() { private Iterator 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 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 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> c) { if (isEmpty(c)) { return new ArrayList<>(); } else if (c.size() == 1) { return newArrayList(c.iterator().next()); } for (final Collection e : c) { if (isEmpty(e)) { return new ArrayList<>(); } } final Iterator> 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 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 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 a, final Collection 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 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 a, final Collection 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 a, final Collection b) { if (isEmpty(a) || isEmpty(b)) { return newHashSet(); } return commonSet(Array.asList(a, (Collection) 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> c) { if (isEmpty(c)) { return newHashSet(); } else if (c.size() == 1) { return newHashSet(c.iterator().next()); } Collection smallest = null; for (final Collection 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 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 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 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 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 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 excludeAll(final Collection c, final Collection objsToExclude) { if (isEmpty(c)) { return new ArrayList<>(); } else if (isEmpty(objsToExclude)) { return new ArrayList<>(c); } else if (objsToExclude.size() == 1) { return exclude(c, firstOrNullIfEmpty(objsToExclude)); } final Set set = objsToExclude instanceof Set ? ((Set) objsToExclude) : new HashSet<>(objsToExclude); final List result = new ArrayList<>(max(0, c.size() - set.size())); for (final T e : c) { if (!set.contains(e)) { result.add(e); } } return result; } /** * Returns a new {@code Set} 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 Set} with the specified objects 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 excludeAllToSet(final Collection c, final Collection objsToExclude) { if (isEmpty(c)) { return new HashSet<>(); } else if (isEmpty(objsToExclude)) { return new HashSet<>(c); } else if (objsToExclude.size() == 1) { return excludeToSet(c, firstOrNullIfEmpty(objsToExclude)); } final Set set = objsToExclude instanceof Set ? ((Set) objsToExclude) : new HashSet<>(objsToExclude); final Set result = c instanceof List || c instanceof LinkedHashSet ? newLinkedHashSet(max(0, c.size() - set.size())) : newHashSet(max(0, c.size() - set.size())); for (final T e : c) { if (!set.contains(e)) { result.add(e); } } return result; } /** * Returns {@code true} if subColl is a sub-collection of coll, * that is, if the cardinality of e in subColl is less than or * equal to the cardinality of e in coll, for each element e * in subColl. * * @param subColl the first (sub?) collection, must not be null * @param coll the second (super?) collection, must not be null * @return {@code true} if subColl is a sub-collection of coll * @throws IllegalArgumentException if {@code subColl} or {@code coll} is {@code null} * @see #isProperSubCollection * @see Collection#containsAll */ public static boolean isSubCollection(@NotNull final Collection subColl, @NotNull final Collection coll) throws IllegalArgumentException { checkArgNotNull(subColl, cs.subColl); checkArgNotNull(coll, cs.coll); if (isEmpty(subColl)) { return true; } else if (isEmpty(coll)) { return false; } if (subColl.size() > coll.size()) { return false; } final Multiset multisetA = Multiset.create(subColl); final Multiset multisetB = Multiset.create(coll); for (final Object e : multisetA.elementSet()) { if (multisetA.occurrencesOf(e) > multisetB.occurrencesOf(e)) { return false; } } return true; } /** * Returns {@code true} if subColl is a proper sub-collection of coll, * that is, if the cardinality of e in subColl is less * than or equal to the cardinality of e in coll, * for each element e in subColl, and there is at least one * element f such that the cardinality of f in coll * is strictly greater than the cardinality of f in subColl. *

* The implementation assumes *

*
    *
  • {@code subColl.size()} and {@code coll.size()} represent the * total cardinality of a and b, resp.
  • *
  • subColl.size() < Integer.MAXVALUE
  • *
* * @param subColl the first (sub?) collection, must not be null * @param coll the second (super?) collection, must not be null * @return {@code true} if subColl is a proper sub-collection of coll * @throws IllegalArgumentException if {@code subColl} or {@code coll} is {@code null} * @see #isSubCollection * @see Collection#containsAll */ public static boolean isProperSubCollection(@NotNull final Collection subColl, final @NotNull Collection coll) throws IllegalArgumentException { checkArgNotNull(subColl, cs.subColl); checkArgNotNull(coll, cs.coll); return subColl.size() < coll.size() && isSubCollection(subColl, coll); } /** * Returns {@code true} if the given {@link Collection}s contain * exactly the same elements with exactly the same cardinalities. *

* That is, if the cardinality of e in a is * equal to the cardinality of e in b, * for each element e in a or b. *

* * @param a the first collection * @param b the second collection * @return {@code true} if the collections contain the same elements with the same cardinalities. */ public static boolean isEqualCollection(final Collection a, final Collection b) { if (a == null && b == null) { return true; } else if ((a == null) == (b != null)) { //NOSONAR return false; } final int sizeA = size(a); final int sizeB = size(b); if (sizeA != sizeB) { return false; } final Multiset multisetA = Multiset.create(a); final Multiset multisetB = Multiset.create(b); if (multisetA.size() != multisetB.size()) { return false; } for (final Object e : multisetA.elementSet()) { if (multisetA.occurrencesOf(e) != multisetB.occurrencesOf(e)) { return false; } } return true; } /** * Replaces all elements in the given boolean array that satisfy the provided predicate with a specified boolean value. * * @param a The boolean array in which to replace values. * @param predicate The predicate used to determine which elements should be replaced. * @param newValue The boolean value to replace with if the predicate is satisfied. * @return The number of replacements made. If the input array is empty or {@code null}, zero is returned. */ public static int replaceIf(final boolean[] a, final BooleanPredicate predicate, final boolean newValue) { if (isEmpty(a)) { return 0; } int result = 0; for (int i = 0, n = a.length; i < n; i++) { if (predicate.test(a[i])) { a[i] = newValue; result++; } } return result; } /** * Replaces all elements in the given char array that satisfy the provided predicate with a specified char value. * * @param a The char array to be modified. * @param predicate The predicate used to determine which elements should be replaced. * @param newValue The char value to replace all elements that satisfy the predicate. * @return The number of replacements made. If the input array is empty or {@code null}, zero is returned. */ public static int replaceIf(final char[] a, final CharPredicate predicate, final char newValue) { if (isEmpty(a)) { return 0; } int result = 0; for (int i = 0, n = a.length; i < n; i++) { if (predicate.test(a[i])) { a[i] = newValue; result++; } } return result; } /** * Replaces all elements in the given byte array that satisfy the provided predicate with a specified byte value. * * @param a The byte array to be modified. * @param predicate The predicate used to determine which elements should be replaced. * @param newValue The byte value to replace all elements that satisfy the predicate. * @return The number of replacements made. If the input array is empty or {@code null}, zero is returned. */ public static int replaceIf(final byte[] a, final BytePredicate predicate, final byte newValue) { if (isEmpty(a)) { return 0; } int result = 0; for (int i = 0, n = a.length; i < n; i++) { if (predicate.test(a[i])) { a[i] = newValue; result++; } } return result; } /** * Replaces all elements in the given short array that satisfy the provided predicate with a specified short value. * * @param a The short array to be modified. * @param predicate The predicate used to determine which elements should be replaced. * @param newValue The short value to replace all elements that satisfy the predicate. * @return The number of replacements made. If the input array is empty or {@code null}, zero is returned. */ public static int replaceIf(final short[] a, final ShortPredicate predicate, final short newValue) { if (isEmpty(a)) { return 0; } int result = 0; for (int i = 0, n = a.length; i < n; i++) { if (predicate.test(a[i])) { a[i] = newValue; result++; } } return result; } /** * Replaces all elements in the given int array that satisfy the provided predicate with a specified int value. * * @param a The int array to be modified. * @param predicate The predicate used to determine which elements should be replaced. * @param newValue The int value to replace all elements that satisfy the predicate. * @return The number of replacements made. If the input array is empty or {@code null}, zero is returned. */ public static int replaceIf(final int[] a, final IntPredicate predicate, final int newValue) { if (isEmpty(a)) { return 0; } int result = 0; for (int i = 0, n = a.length; i < n; i++) { if (predicate.test(a[i])) { a[i] = newValue; result++; } } return result; } /** * Replaces all elements in the given long array that satisfy the provided predicate with a specified long value. * * @param a The long array to be modified. * @param predicate The predicate used to determine which elements should be replaced. * @param newValue The long value to replace all elements that satisfy the predicate. * @return The number of replacements made. If the input array is empty or {@code null}, zero is returned. */ public static int replaceIf(final long[] a, final LongPredicate predicate, final long newValue) { if (isEmpty(a)) { return 0; } int result = 0; for (int i = 0, n = a.length; i < n; i++) { if (predicate.test(a[i])) { a[i] = newValue; result++; } } return result; } /** * Replaces all elements in the given float array that satisfy the provided predicate with a specified float value. * * @param a The float array to be modified. * @param predicate The predicate used to determine which elements should be replaced. * @param newValue The float value to replace all elements that satisfy the predicate. * @return The number of replacements made. If the input array is empty or {@code null}, zero is returned. */ public static int replaceIf(final float[] a, final FloatPredicate predicate, final float newValue) { if (isEmpty(a)) { return 0; } int result = 0; for (int i = 0, n = a.length; i < n; i++) { if (predicate.test(a[i])) { a[i] = newValue; result++; } } return result; } /** * Replaces all elements in the given double array that satisfy the provided predicate with a specified double value. * * @param a The double array to be modified. * @param predicate The predicate used to determine which elements should be replaced. * @param newValue The double value to replace all elements that satisfy the predicate. * @return The number of replacements made. If the input array is empty or {@code null}, zero is returned. */ public static int replaceIf(final double[] a, final DoublePredicate predicate, final double newValue) { if (isEmpty(a)) { return 0; } int result = 0; for (int i = 0, n = a.length; i < n; i++) { if (predicate.test(a[i])) { a[i] = newValue; result++; } } return result; } /** * Replaces all elements in the given array that satisfy the provided predicate with a specified value. * * @param The type of elements in the array. * @param a The array to be modified. * @param predicate The predicate used to determine which elements should be replaced. * @param newValue The value to replace all elements that satisfy the predicate. * @return The number of replacements made. If the input array is empty or {@code null}, zero is returned. */ public static int replaceIf(final T[] a, final Predicate predicate, final T newValue) { if (isEmpty(a)) { return 0; } int result = 0; for (int i = 0, n = a.length; i < n; i++) { if (predicate.test(a[i])) { a[i] = newValue; result++; } } return result; } /** * Replaces all elements in the given list that satisfy the provided predicate with a specified value. * * @param The type of elements in the list. * @param list The list to be modified. * @param predicate The predicate used to determine which elements should be replaced. * @param newValue The value to replace all elements that satisfy the predicate. * @return The number of replacements made. If the input list is empty or {@code null}, zero is returned. */ public static int replaceIf(final List list, final Predicate predicate, final T newValue) { if (isEmpty(list)) { return 0; } int result = 0; for (int i = 0, n = list.size(); i < n; i++) { if (predicate.test(list.get(i))) { list.set(i, newValue); result++; } } return result; } /** * Replaces all occurrences of the specified old value with the new value in the given boolean array. * * @param a The boolean array in which to replace values. * @param oldVal The value to be replaced. * @param newVal The value to replace with. * @return The number of replacements made. If the input array is empty or {@code null}, zero is returned. */ public static int replaceAll(final boolean[] a, final boolean oldVal, final boolean newVal) { if (isEmpty(a)) { return 0; } int result = 0; for (int i = 0, len = a.length; i < len; i++) { if (a[i] == oldVal) { a[i] = newVal; result++; } } return result; } /** * Replaces all occurrences of the specified old value with the new value in the given char array. * * @param a The char array in which replacements are to be made. * @param oldVal The char value to be replaced. * @param newVal The char value to replace all occurrences of the oldVal. * @return The number of replacements made. If the input array is empty or {@code null}, zero is returned. */ public static int replaceAll(final char[] a, final char oldVal, final char newVal) { if (isEmpty(a)) { return 0; } int result = 0; for (int i = 0, len = a.length; i < len; i++) { if (a[i] == oldVal) { a[i] = newVal; result++; } } return result; } /** * Replaces all occurrences of the specified old value with the new value in the given byte array. * * @param a The byte array in which to replace values. * @param oldVal The value to be replaced. * @param newVal The value to replace with. * @return The number of replacements made. If the input array is empty or {@code null}, zero is returned. */ public static int replaceAll(final byte[] a, final byte oldVal, final byte newVal) { if (isEmpty(a)) { return 0; } int result = 0; for (int i = 0, len = a.length; i < len; i++) { if (a[i] == oldVal) { a[i] = newVal; result++; } } return result; } /** * Replaces all occurrences of the specified old value with the new value in the given short array. * * @param a The short array in which to replace values. * @param oldVal The value to be replaced. * @param newVal The value to replace with. * @return The number of replacements made. If the input array is empty or {@code null}, zero is returned. */ public static int replaceAll(final short[] a, final short oldVal, final short newVal) { if (isEmpty(a)) { return 0; } int result = 0; for (int i = 0, len = a.length; i < len; i++) { if (a[i] == oldVal) { a[i] = newVal; result++; } } return result; } /** * Replaces all occurrences of the specified old value with the new value in the given int array. * * @param a The int array in which to replace values. * @param oldVal The value to be replaced. * @param newVal The value to replace with. * @return The number of replacements made. If the input array is empty or {@code null}, zero is returned. */ public static int replaceAll(final int[] a, final int oldVal, final int newVal) { if (isEmpty(a)) { return 0; } int result = 0; for (int i = 0, len = a.length; i < len; i++) { if (a[i] == oldVal) { a[i] = newVal; result++; } } return result; } /** * Replaces all occurrences of the specified old value with the new value in the given long array. * * @param a The long array in which to replace values. * @param oldVal The value to be replaced. * @param newVal The value to replace with. * @return The number of replacements made. If the input array is empty or {@code null}, zero is returned. */ public static int replaceAll(final long[] a, final long oldVal, final long newVal) { if (isEmpty(a)) { return 0; } int result = 0; for (int i = 0, len = a.length; i < len; i++) { if (a[i] == oldVal) { a[i] = newVal; result++; } } return result; } /** * Replaces all occurrences of the specified old value with the new value in the given float array. * * @param a The float array in which to replace values. * @param oldVal The value to be replaced. * @param newVal The value to replace with. * @return The number of replacements made. If the input array is empty or {@code null}, zero is returned. */ public static int replaceAll(final float[] a, final float oldVal, final float newVal) { if (isEmpty(a)) { return 0; } int result = 0; for (int i = 0, len = a.length; i < len; i++) { if (Float.compare(a[i], oldVal) == 0) { a[i] = newVal; result++; } } return result; } /** * Replaces all occurrences of the specified old value with the new value in the given double array. * * @param a The double array in which to replace values. * @param oldVal The value to be replaced. * @param newVal The value to replace with. * @return The number of replacements made. If the input array is empty or {@code null}, zero is returned. */ public static int replaceAll(final double[] a, final double oldVal, final double newVal) { if (isEmpty(a)) { return 0; } int result = 0; for (int i = 0, len = a.length; i < len; i++) { if (Double.compare(a[i], oldVal) == 0) { a[i] = newVal; result++; } } return result; } /** * Replaces all occurrences of the specified old value with the new value in the given array. * * @param The type of elements in the array. * @param a The array in which to replace values. * @param oldVal The value to be replaced. * @param newVal The value to replace with. * @return The number of replacements made. If the input array is empty or {@code null}, zero is returned. */ public static int replaceAll(final T[] a, final Object oldVal, final T newVal) { if (isEmpty(a)) { return 0; } int result = 0; if (oldVal == null) { for (int i = 0, len = a.length; i < len; i++) { if (a[i] == null) { a[i] = newVal; result++; } } } else { for (int i = 0, len = a.length; i < len; i++) { if (equals(a[i], oldVal)) { a[i] = newVal; result++; } } } return result; } /** * Replaces all occurrences of the specified old value with the new value in the given list. * * @param The type of elements in the list. * @param list The list in which to replace values. * @param oldVal The value to be replaced. * @param newVal The value to replace with. * @return The number of replacements made. If the input list is empty or {@code null}, zero is returned. */ public static int replaceAll(final List list, final Object oldVal, final T newVal) { if (isEmpty(list)) { return 0; } int result = 0; final int size = list.size(); if (size < REPLACE_ALL_THRESHOLD || list instanceof RandomAccess) { if (oldVal == null) { for (int i = 0; i < size; i++) { if (list.get(i) == null) { list.set(i, newVal); result++; } } } else { for (int i = 0; i < size; i++) { if (oldVal.equals(list.get(i))) { list.set(i, newVal); result++; } } } } else { final ListIterator itr = list.listIterator(); if (oldVal == null) { for (int i = 0; i < size; i++) { if (itr.next() == null) { itr.set(newVal); result++; } } } else { for (int i = 0; i < size; i++) { if (oldVal.equals(itr.next())) { itr.set(newVal); result++; } } } } return result; } /** * Replaces all elements in the given boolean array using the specified {@code BooleanUnaryOperator}. * If the input array is empty or {@code null}, no replacements are made. * * @param a The boolean array in which to replace values. * @param operator The BooleanUnaryOperator to apply to each element. The operator takes a boolean value and returns a boolean value. * @see #setAll(boolean[], IntToBooleanFunction) */ public static void replaceAll(final boolean[] a, final BooleanUnaryOperator operator) { if (isEmpty(a)) { return; } for (int i = 0, n = a.length; i < n; i++) { a[i] = operator.applyAsBoolean(a[i]); } } /** * Replaces all elements in the given char array using the specified {@code CharUnaryOperator}. * If the input array is empty or {@code null}, no replacements are made. * * @param a The char array in which to replace values. * @param operator The CharUnaryOperator to apply to each element. The operator takes a char value and returns a char value. * @see #setAll(char[], IntToCharFunction) */ public static void replaceAll(final char[] a, final CharUnaryOperator operator) { if (isEmpty(a)) { return; } for (int i = 0, n = a.length; i < n; i++) { a[i] = operator.applyAsChar(a[i]); } } /** * Replaces all elements in the given byte array using the specified {@code ByteUnaryOperator}. * If the input array is empty or {@code null}, no replacements are made. * * @param a The byte array in which to replace values. * @param operator The ByteUnaryOperator to apply to each element. The operator takes a byte value and returns a byte value. * @see #setAll(byte[], IntToByteFunction) */ public static void replaceAll(final byte[] a, final ByteUnaryOperator operator) { if (isEmpty(a)) { return; } for (int i = 0, n = a.length; i < n; i++) { a[i] = operator.applyAsByte(a[i]); } } /** * Replaces all elements in the given short array using the specified {@code ShortUnaryOperator}. * If the input array is empty or {@code null}, no replacements are made. * * @param a The short array in which to replace values. * @param operator The ShortUnaryOperator to apply to each element. The operator takes a short value and returns a short value. * @see #setAll(short[], IntToShortFunction) */ public static void replaceAll(final short[] a, final ShortUnaryOperator operator) { if (isEmpty(a)) { return; } for (int i = 0, n = a.length; i < n; i++) { a[i] = operator.applyAsShort(a[i]); } } /** * Replaces all elements in the given int array using the specified {@code IntUnaryOperator}. * If the input array is empty or {@code null}, no replacements are made. * * @param a The int array in which to replace values. * @param operator The IntUnaryOperator to apply to each element. The operator takes an int value and returns an int value. * @see #setAll(int[], IntUnaryOperator) * @see Arrays#setAll(int[], IntUnaryOperator) * @see Arrays#parallelSetAll(int[], IntUnaryOperator) */ public static void replaceAll(final int[] a, final IntUnaryOperator operator) { if (isEmpty(a)) { return; } for (int i = 0, n = a.length; i < n; i++) { a[i] = operator.applyAsInt(a[i]); } } /** * Replaces all elements in the given long array using the specified {@code LongUnaryOperator}. * If the input array is empty or {@code null}, no replacements are made. * * @param a The long array in which to replace values. * @param operator The LongUnaryOperator to apply to each element. The operator takes a long value and returns a long value. * @see #setAll(long[], IntToLongFunction) * @see Arrays#setAll(long[], IntToLongFunction) * @see Arrays#parallelSetAll(long[], IntToLongFunction) */ public static void replaceAll(final long[] a, final LongUnaryOperator operator) { if (isEmpty(a)) { return; } for (int i = 0, n = a.length; i < n; i++) { a[i] = operator.applyAsLong(a[i]); } } /** * Replaces all elements in the given float array using the specified {@code FloatUnaryOperator}. * If the input array is empty or {@code null}, no replacements are made. * * @param a The float array in which to replace values. * @param operator The FloatUnaryOperator to apply to each element. The operator takes a float value and returns a float value. * @see #setAll(float[], IntToFloatFunction) */ public static void replaceAll(final float[] a, final FloatUnaryOperator operator) { if (isEmpty(a)) { return; } for (int i = 0, n = a.length; i < n; i++) { a[i] = operator.applyAsFloat(a[i]); } } /** * Replaces all elements in the given double array using the specified {@code DoubleUnaryOperator}. * If the input array is empty or {@code null}, no replacements are made. * * @param a The double array in which to replace values. * @param operator The DoubleUnaryOperator to apply to each element. The operator takes a double value and returns a double value. * @see #setAll(double[], IntToDoubleFunction) * @see Arrays#setAll(double[], IntToDoubleFunction) * @see Arrays#parallelSetAll(double[], IntToDoubleFunction) */ public static void replaceAll(final double[] a, final DoubleUnaryOperator operator) { if (isEmpty(a)) { return; } for (int i = 0, n = a.length; i < n; i++) { a[i] = operator.applyAsDouble(a[i]); } } /** * Replaces all elements in the given array using the specified {@code UnaryOperator}. * If the input array is empty or {@code null}, no replacements are made. * * @param The type of elements in the array. * @param a The array in which to replace values. * @param operator The UnaryOperator to apply to each element. The operator takes a value of type T and returns a value of type T. * @see #setAll(Object[], IntFunction) * @see #setAll(Object[], Throwables.IntObjFunction) * @see Arrays#setAll(Object[], IntFunction) * @see Arrays#parallelSetAll(Object[], IntFunction) */ public static void replaceAll(final T[] a, final UnaryOperator operator) { if (isEmpty(a)) { return; } for (int i = 0, n = a.length; i < n; i++) { a[i] = operator.apply(a[i]); } } /** * Replaces all elements in the given list using the specified {@code UnaryOperator}. * If the input list is empty or {@code null}, no replacements are made. * * @param The type of elements in the list. * @param list The list in which to replace values. * @param operator The UnaryOperator to apply to each element. The operator takes a value of type T and returns a value of type T. * @see #setAll(List, IntFunction) * @see #setAll(List, Throwables.IntObjFunction) */ public static void replaceAll(final List list, final UnaryOperator operator) { if (isEmpty(list)) { return; } final int size = list.size(); if (size < REPLACE_ALL_THRESHOLD || list instanceof RandomAccess) { for (int i = 0; i < size; i++) { list.set(i, operator.apply(list.get(i))); } } else { final ListIterator itr = list.listIterator(); for (int i = 0; i < size; i++) { itr.set(operator.apply(itr.next())); } } } /** * Replaces all elements in the given array using the specified {@code UnaryOperator}. * If the input array is empty or {@code null}, no replacements are made. * * @param The type of elements in the array. * @param The type of exception may thrown out. * @param a The array in which to replace values. * @param operator The UnaryOperator to apply to each element. The operator takes a value of type T and returns a value of type T. * @throws E the exception may be thrown out. * @see #replaceAll(Object[], UnaryOperator) * @see #setAll(Object[], IntFunction) * @see #setAll(Object[], Throwables.IntObjFunction) * @see Arrays#setAll(Object[], IntFunction) * @see Arrays#parallelSetAll(Object[], IntFunction) */ @Beta public static void updateAll(final T[] a, final Throwables.UnaryOperator operator) throws E { if (isEmpty(a)) { return; } for (int i = 0, n = a.length; i < n; i++) { a[i] = operator.apply(a[i]); } } /** * Replaces all elements in the given list using the specified {@code UnaryOperator}. * If the input list is empty or {@code null}, no replacements are made. * * @param The type of elements in the list. * @param The type of exception may thrown out. * @param list The list in which to replace values. * @param operator The UnaryOperator to apply to each element. The operator takes a value of type T and returns a value of type T. * @throws E the exception may be thrown out. * @see #replaceAll(List, UnaryOperator) * @see #setAll(List, IntFunction) * @see #setAll(List, Throwables.IntObjFunction) */ @Beta public static void updateAll(final List list, final Throwables.UnaryOperator operator) throws E { if (isEmpty(list)) { return; } final int size = list.size(); if (size < REPLACE_ALL_THRESHOLD || list instanceof RandomAccess) { for (int i = 0; i < size; i++) { list.set(i, operator.apply(list.get(i))); } } else { final ListIterator itr = list.listIterator(); for (int i = 0; i < size; i++) { itr.set(operator.apply(itr.next())); } } } /** * A fake/unsupported method defined to remind user to use {@code replaceAll} when {@code update/updateAll/updateIf} is searched. * * @throws UnsupportedOperationException * @see #replaceAll(Object[], UnaryOperator) * @see #replaceAll(Object[], Object, Object) * @deprecated use {@code replaceAll} */ @Deprecated public static void updateAllUsingReplaceAllInstead() throws UnsupportedOperationException { throw new UnsupportedOperationException("Fake method. Please use 'replaceAll'"); } /** * A fake/unsupported method defined to remind user to use {@code replaceIf} when {@code update/updateAll/updateIf} is searched. * * @throws UnsupportedOperationException * @see #replaceIf(Object[], Predicate, Object) * @deprecated use {@code replaceIf} */ @Deprecated public static void updateIfUsingReplaceIfInstead() throws UnsupportedOperationException { throw new UnsupportedOperationException("Fake method. Please use 'replaceIf'"); } /** * Sets all elements in the given array using the provided generator function. * If the specified array is {@code null} or empty, does nothing. * * @param array the array to be modified * @param generator the function used to generate new values for the array elements * @see #replaceAll(boolean[], BooleanUnaryOperator) * @see Arrays#setAll(int[], IntUnaryOperator) * @see Arrays#parallelSetAll(int[], IntUnaryOperator); */ public static void setAll(final boolean[] array, final IntToBooleanFunction generator) { if (isEmpty(array)) { return; } for (int i = 0, len = array.length; i < len; i++) { array[i] = generator.applyAsBoolean(i); } } /** * Sets all elements in the given array using the provided generator function. * If the specified array is {@code null} or empty, does nothing. * * @param array the array to be modified * @param generator the function used to generate new values for the array elements * @see #replaceAll(char[], CharUnaryOperator) * @see Arrays#setAll(int[], IntUnaryOperator) * @see Arrays#parallelSetAll(int[], IntUnaryOperator); */ public static void setAll(final char[] array, final IntToCharFunction generator) { if (isEmpty(array)) { return; } for (int i = 0, len = array.length; i < len; i++) { array[i] = generator.applyAsChar(i); } } /** * Sets all elements in the given array using the provided generator function. * If the specified array is {@code null} or empty, does nothing. * * @param array the array to be modified * @param generator the function used to generate new values for the array elements * @see #replaceAll(byte[], ByteUnaryOperator) * @see Arrays#setAll(int[], IntUnaryOperator) * @see Arrays#parallelSetAll(int[], IntUnaryOperator); */ public static void setAll(final byte[] array, final IntToByteFunction generator) { if (isEmpty(array)) { return; } for (int i = 0, len = array.length; i < len; i++) { array[i] = generator.applyAsByte(i); } } /** * Sets all elements in the given array using the provided generator function. * If the specified array is {@code null} or empty, does nothing. * * @param array the array to be modified * @param generator the function used to generate new values for the array elements * @see #replaceAll(short[], ShortUnaryOperator) * @see Arrays#setAll(int[], IntUnaryOperator) * @see Arrays#parallelSetAll(int[], IntUnaryOperator); */ public static void setAll(final short[] array, final IntToShortFunction generator) { if (isEmpty(array)) { return; } for (int i = 0, len = array.length; i < len; i++) { array[i] = generator.applyAsShort(i); } } /** * Sets all elements in the given array using the provided generator function. * If the specified array is {@code null} or empty, does nothing. * * @param array the array to be modified * @param generator the function used to generate new values for the array elements * @see #replaceAll(int[], IntUnaryOperator) * @see Arrays#setAll(int[], IntUnaryOperator) * @see Arrays#parallelSetAll(int[], IntUnaryOperator); */ public static void setAll(final int[] array, final IntUnaryOperator generator) { if (isEmpty(array)) { return; } Arrays.setAll(array, generator); } /** * Sets all elements in the given array using the provided generator function. * If the specified array is {@code null} or empty, does nothing. * * @param array the array to be modified * @param generator the function used to generate new values for the array elements * @see #replaceAll(long[], LongUnaryOperator) * @see Arrays#setAll(long[], IntToLongFunction) * @see Arrays#parallelSetAll(long[], IntToLongFunction) */ public static void setAll(final long[] array, final IntToLongFunction generator) { if (isEmpty(array)) { return; } Arrays.setAll(array, generator); } /** * Sets all elements in the given array using the provided generator function. * If the specified array is {@code null} or empty, does nothing. * * @param array the array to be modified * @param generator the function used to generate new values for the array elements * @see #replaceAll(float[], FloatUnaryOperator) * @see Arrays#setAll(double[], IntToDoubleFunction) * @see Arrays#parallelSetAll(double[], IntToDoubleFunction) */ public static void setAll(final float[] array, final IntToFloatFunction generator) { if (isEmpty(array)) { return; } for (int i = 0, len = array.length; i < len; i++) { array[i] = generator.applyAsFloat(i); } } /** * Sets all elements in the given array using the provided generator function. * If the specified array is {@code null} or empty, does nothing. * * @param array the array to be modified * @param generator the function used to generate new values for the array elements * @see #replaceAll(double[], DoubleUnaryOperator) * @see Arrays#setAll(double[], IntToDoubleFunction) * @see Arrays#parallelSetAll(double[], IntToDoubleFunction) */ public static void setAll(final double[] array, final IntToDoubleFunction generator) { if (isEmpty(array)) { return; } Arrays.setAll(array, generator); } /** * Sets all elements in the given array using the provided generator function. * If the specified array is {@code null} or empty, does nothing. * * @param the type of elements in the input array * @param array the array to be modified * @param generator the function used to generate new values for the array elements * @see #replaceAll(Object[], UnaryOperator) * @see #setAll(Object[], Throwables.IntObjFunction) * @see Arrays#setAll(Object[], IntFunction) * @see Arrays#parallelSetAll(Object[], IntFunction) */ public static void setAll(final T[] array, final IntFunction generator) { if (isEmpty(array)) { return; } Arrays.setAll(array, generator); } /** * Sets all elements in the given list using the provided generator function. * If the specified list is {@code null} or empty, does nothing. * * @param the type of elements in the list * @param list the list to be modified * @param generator the function used to generate new values for the list elements * @see #replaceAll(List, UnaryOperator) * @see #setAll(List, Throwables.IntObjFunction) */ public static void setAll(final List list, final IntFunction generator) { if (isEmpty(list)) { return; } final int size = list.size(); if (size < REPLACE_ALL_THRESHOLD || list instanceof RandomAccess) { for (int i = 0; i < size; i++) { list.set(i, generator.apply(i)); } } else { final ListIterator itr = list.listIterator(); final MutableInt idx = MutableInt.of(0); for (int i = 0; i < size; i++) { itr.set(generator.apply(idx.getAndIncrement())); } } } /** * Sets all elements in the given array using the provided converter function. * If the specified array is {@code null} or empty, does nothing. * * @param the type of elements in the array * @param the type of exception that the converter may throw * @param a the array to be modified * @param converter the function used to generate new values for the array elements with the index of the element as the first parameter and the original element as the second parameter * @throws E if the converter function throws an exception * @see #replaceAll(Object[], UnaryOperator) * @see #setAll(Object[], IntFunction) * @see Arrays#setAll(Object[], IntFunction) */ @Beta public static void setAll(final T[] a, final Throwables.IntObjFunction converter) throws E { if (isEmpty(a)) { return; } for (int i = 0, len = a.length; i < len; i++) { a[i] = converter.apply(i, a[i]); } } /** * Sets all elements in the given list using the provided converter function. * If the specified list is {@code null} or empty, does nothing. * * @param the type of elements in the list * @param the type of exception that the converter may throw * @param list the list to be modified * @param converter the function used to generate new values for the list elements with the index of the element as the first parameter and the original element as the second parameter * @throws E if the converter function throws an exception * @see #replaceAll(List, UnaryOperator) * @see #setAll(List, IntFunction) * @see Arrays#setAll(Object[], IntFunction) */ @Beta public static void setAll(final List list, final Throwables.IntObjFunction converter) throws E { if (isEmpty(list)) { return; } final int size = list.size(); if (size < REPLACE_ALL_THRESHOLD || list instanceof RandomAccess) { for (int i = 0; i < size; i++) { list.set(i, converter.apply(i, list.get(i))); } } else { final ListIterator iter = list.listIterator(); int idx = 0; while (iter.hasNext()) { iter.set(converter.apply(idx++, iter.next())); } } } /** * Creates a copy of the given array and sets all elements in the copy using the provided generator function. * If the specified array is {@code null}, returns {@code null}. * If the specified array is empty, returns itself. * * @param the type of elements in the array * @param a the array to be copied and modified * @param generator the function used to generate new values for the array elements * @return a new array with elements copied from the specified array and modified by the generator function * @see #copyThenSetAll(Object[], Throwables.IntObjFunction) * @see #copyThenReplaceAll(Object[], UnaryOperator) */ @MayReturnNull public static T[] copyThenSetAll(final T[] a, final IntFunction generator) { if (a == null) { return null; // NOSONAR } else if (a.length == 0) { return a.clone(); } final T[] copy = a.clone(); for (int i = 0, len = a.length; i < len; i++) { copy[i] = generator.apply(i); } return copy; } /** * Creates a copy of the given array and sets all elements in the copy using the provided converter function. * If the specified array is {@code null}, returns {@code null}. * If the specified array is empty, returns itself. * * @param the type of elements in the array * @param the type of exception that the converter may throw * @param a the array to be copied and modified * @param converter the function used to generate new values for the array elements with the index of the element as the first parameter and the original element as the second parameter * @return a new array with elements copied from the specified array and modified by the converter function * @throws E if the converter function throws an exception * @see #copyThenSetAll(Object[], IntFunction) * @see #copyThenReplaceAll(Object[], UnaryOperator) */ @MayReturnNull public static T[] copyThenSetAll(final T[] a, final Throwables.IntObjFunction converter) throws E { if (a == null) { return null; // NOSONAR } else if (a.length == 0) { return a.clone(); } final T[] copy = a.clone(); for (int i = 0, len = a.length; i < len; i++) { copy[i] = converter.apply(i, a[i]); } return copy; } /** * Creates a copy of the given array and replaces all elements in the copy using the provided {@code UnaryOperator}. * If the specified array is {@code null}, returns {@code null}. * If the specified array is empty, returns itself. * * @param the type of elements in the array * @param a the array to be copied and modified * @param operator The UnaryOperator to apply to each element. The operator takes a value of type T and returns a value of type T. * @return a new array with elements copied from the specified array and modified by provided {@code UnaryOperator} * @see #copyThenSetAll(Object[], IntFunction) * @see #copyThenSetAll(Object[], Throwables.IntObjFunction) */ @MayReturnNull public static T[] copyThenReplaceAll(final T[] a, final UnaryOperator operator) { if (a == null) { return null; // NOSONAR } else if (a.length == 0) { return a.clone(); } final T[] copy = a.clone(); for (int i = 0, len = a.length; i < len; i++) { copy[i] = operator.apply(copy[i]); } return a; } /** * Returns a new array with elements copied from the specified array and the specified element added at the end. *
* The original array remains unchanged. * * @param a The original boolean array. * @param elementToAdd The boolean element to be added to the array. * @return A new boolean array containing the original elements and the added element. */ public static boolean[] add(final boolean[] a, final boolean elementToAdd) { if (isEmpty(a)) { return Array.of(elementToAdd); } final boolean[] newArray = new boolean[a.length + 1]; copy(a, 0, newArray, 0, a.length); newArray[a.length] = elementToAdd; return newArray; } /** * Returns a new array with elements copied from the specified array and the specified element added at the end. *
* The original array remains unchanged. * * @param a The original char array. * @param elementToAdd The char element to be added to the array. * @return A new char array containing the original elements and the added element. */ public static char[] add(final char[] a, final char elementToAdd) { if (isEmpty(a)) { return Array.of(elementToAdd); } final char[] newArray = new char[a.length + 1]; copy(a, 0, newArray, 0, a.length); newArray[a.length] = elementToAdd; return newArray; } /** * Returns a new array with elements copied from the specified array and the specified element added at the end. *
* The original array remains unchanged. * * @param a The original byte array. * @param elementToAdd The byte element to be added to the array. * @return A new byte array containing the original elements and the added element. */ public static byte[] add(final byte[] a, final byte elementToAdd) { if (isEmpty(a)) { return Array.of(elementToAdd); } final byte[] newArray = new byte[a.length + 1]; copy(a, 0, newArray, 0, a.length); newArray[a.length] = elementToAdd; return newArray; } /** * Returns a new array with elements copied from the specified array and the specified element added at the end. *
* The original array remains unchanged. * * @param a The original short array. * @param elementToAdd The short element to be added to the array. * @return A new short array containing the original elements and the added element. */ public static short[] add(final short[] a, final short elementToAdd) { if (isEmpty(a)) { return Array.of(elementToAdd); } final short[] newArray = new short[a.length + 1]; copy(a, 0, newArray, 0, a.length); newArray[a.length] = elementToAdd; return newArray; } /** * Returns a new array with elements copied from the specified array and the specified element added at the end. *
* The original array remains unchanged. * * @param a The original int array. * @param elementToAdd The int element to be added to the array. * @return A new int array containing the original elements and the added element. */ public static int[] add(final int[] a, final int elementToAdd) { if (isEmpty(a)) { return Array.of(elementToAdd); } final int[] newArray = new int[a.length + 1]; copy(a, 0, newArray, 0, a.length); newArray[a.length] = elementToAdd; return newArray; } /** * Returns a new array with elements copied from the specified array and the specified element added at the end. *
* The original array remains unchanged. * * @param a The original long array. * @param elementToAdd The long element to be added to the array. * @return A new long array containing the original elements and the added element. */ public static long[] add(final long[] a, final long elementToAdd) { if (isEmpty(a)) { return Array.of(elementToAdd); } final long[] newArray = new long[a.length + 1]; copy(a, 0, newArray, 0, a.length); newArray[a.length] = elementToAdd; return newArray; } /** * Returns a new array with elements copied from the specified array and the specified element added at the end. *
* The original array remains unchanged. * * @param a The original float array. * @param elementToAdd The float element to be added to the array. * @return A new float array containing the original elements and the added element. */ public static float[] add(final float[] a, final float elementToAdd) { if (isEmpty(a)) { return Array.of(elementToAdd); } final float[] newArray = new float[a.length + 1]; copy(a, 0, newArray, 0, a.length); newArray[a.length] = elementToAdd; return newArray; } /** * Returns a new array with elements copied from the specified array and the specified element added at the end. *
* The original array remains unchanged. * * @param a The original double array. * @param elementToAdd The double element to be added to the array. * @return A new double array containing the original elements and the added element. */ public static double[] add(final double[] a, final double elementToAdd) { if (isEmpty(a)) { return Array.of(elementToAdd); } final double[] newArray = new double[a.length + 1]; copy(a, 0, newArray, 0, a.length); newArray[a.length] = elementToAdd; return newArray; } /** * Returns a new array with elements copied from the specified array and the specified element added at the end. *
* The original array remains unchanged. * * @param a The original String array. * @param elementToAdd The String element to be added to the array. * @return A new String array containing the original elements and the added element. */ public static String[] add(final String[] a, final String elementToAdd) { if (isEmpty(a)) { return asArray(elementToAdd); } final String[] newArray = new String[a.length + 1]; copy(a, 0, newArray, 0, a.length); newArray[a.length] = elementToAdd; return newArray; } /** * Returns a new array with elements copied from the specified array and the specified element added at the end. *
* The original array remains unchanged. * * @param The type of elements in the array. * @param a The original array. * @param elementToAdd The element to be added to the array. * @return A new array containing the original elements and the added element. * @throws IllegalArgumentException if the original array is {@code null}. */ public static T[] add(@NotNull final T[] a, final T elementToAdd) throws IllegalArgumentException { checkArgNotNull(a, cs.a); final int len = a.length; final T[] newArray = Array.newInstance(a.getClass().getComponentType(), len + 1); if (len > 0) { copy(a, 0, newArray, 0, len); } newArray[len] = elementToAdd; return newArray; } /** * Returns a new array with elements copied from the specified array and the specified element added at the end. *
* The original array remains unchanged. * * @param a The first array whose elements are added to the new array. * @param elementsToAdd The additional elements to be added to the new array. * @return A new boolean array containing the elements from a and elementsToAdd. */ @SafeVarargs public static boolean[] addAll(final boolean[] a, final boolean... elementsToAdd) { if (isEmpty(a)) { return isEmpty(elementsToAdd) ? EMPTY_BOOLEAN_ARRAY : elementsToAdd.clone(); } final boolean[] newArray = new boolean[a.length + elementsToAdd.length]; copy(a, 0, newArray, 0, a.length); copy(elementsToAdd, 0, newArray, a.length, elementsToAdd.length); return newArray; } /** * Returns a new array with elements copied from the specified array and the specified element added at the end. *
* The original array remains unchanged. * * @param a The first array whose elements are added to the new array. * @param elementsToAdd The additional elements to be added to the new array. * @return A new char array containing the elements from a and elementsToAdd. */ @SafeVarargs public static char[] addAll(final char[] a, final char... elementsToAdd) { if (isEmpty(a)) { return isEmpty(elementsToAdd) ? EMPTY_CHAR_ARRAY : elementsToAdd.clone(); } final char[] newArray = new char[a.length + elementsToAdd.length]; copy(a, 0, newArray, 0, a.length); copy(elementsToAdd, 0, newArray, a.length, elementsToAdd.length); return newArray; } /** * Returns a new array with elements copied from the specified array and the specified elements added at the end. *
* The original array remains unchanged. * * @param a The first array whose elements are added to the new array. * @param elementsToAdd The additional elements to be added to the new array. * @return A new byte array containing the elements from a and elementsToAdd. */ @SafeVarargs public static byte[] addAll(final byte[] a, final byte... elementsToAdd) { if (isEmpty(a)) { return isEmpty(elementsToAdd) ? EMPTY_BYTE_ARRAY : elementsToAdd.clone(); } final byte[] newArray = new byte[a.length + elementsToAdd.length]; copy(a, 0, newArray, 0, a.length); copy(elementsToAdd, 0, newArray, a.length, elementsToAdd.length); return newArray; } /** * Returns a new array with elements copied from the specified array and the specified elements added at the end. *
* The original array remains unchanged. * * @param a The first array whose elements are added to the new array. * @param elementsToAdd The additional elements to be added to the new array. * @return A new short array containing the elements from a and elementsToAdd. */ @SafeVarargs public static short[] addAll(final short[] a, final short... elementsToAdd) { if (isEmpty(a)) { return isEmpty(elementsToAdd) ? EMPTY_SHORT_ARRAY : elementsToAdd.clone(); } final short[] newArray = new short[a.length + elementsToAdd.length]; copy(a, 0, newArray, 0, a.length); copy(elementsToAdd, 0, newArray, a.length, elementsToAdd.length); return newArray; } /** * Returns a new array with elements copied from the specified array and the specified elements added at the end. *
* The original array remains unchanged. * * @param a The first array whose elements are added to the new array. * @param elementsToAdd The additional elements to be added to the new array. * @return A new int array containing the elements from a and elementsToAdd. */ @SafeVarargs public static int[] addAll(final int[] a, final int... elementsToAdd) { if (isEmpty(a)) { return isEmpty(elementsToAdd) ? EMPTY_INT_ARRAY : elementsToAdd.clone(); } final int[] newArray = new int[a.length + elementsToAdd.length]; copy(a, 0, newArray, 0, a.length); copy(elementsToAdd, 0, newArray, a.length, elementsToAdd.length); return newArray; } /** * Returns a new array with elements copied from the specified array and the specified elements added at the end. *
* The original array remains unchanged. * * @param a The first array whose elements are added to the new array. * @param elementsToAdd The additional elements to be added to the new array. * @return A new long array containing the elements from a and elementsToAdd. */ @SafeVarargs public static long[] addAll(final long[] a, final long... elementsToAdd) { if (isEmpty(a)) { return isEmpty(elementsToAdd) ? EMPTY_LONG_ARRAY : elementsToAdd.clone(); } final long[] newArray = new long[a.length + elementsToAdd.length]; copy(a, 0, newArray, 0, a.length); copy(elementsToAdd, 0, newArray, a.length, elementsToAdd.length); return newArray; } /** * Returns a new array with elements copied from the specified array and the specified elements added at the end. *
* The original array remains unchanged. * * @param a The first array whose elements are added to the new array. * @param elementsToAdd The additional elements to be added to the new array. * @return A new float array containing the elements from a and elementsToAdd. */ @SafeVarargs public static float[] addAll(final float[] a, final float... elementsToAdd) { if (isEmpty(a)) { return isEmpty(elementsToAdd) ? EMPTY_FLOAT_ARRAY : elementsToAdd.clone(); } final float[] newArray = new float[a.length + elementsToAdd.length]; copy(a, 0, newArray, 0, a.length); copy(elementsToAdd, 0, newArray, a.length, elementsToAdd.length); return newArray; } /** * Returns a new array with elements copied from the specified array and the specified elements added at the end. *
* The original array remains unchanged. * * @param a The first array whose elements are added to the new array. * @param elementsToAdd The additional elements to be added to the new array. * @return A new double array containing the elements from a and elementsToAdd. */ @SafeVarargs public static double[] addAll(final double[] a, final double... elementsToAdd) { if (isEmpty(a)) { return isEmpty(elementsToAdd) ? EMPTY_DOUBLE_ARRAY : elementsToAdd.clone(); } final double[] newArray = new double[a.length + elementsToAdd.length]; copy(a, 0, newArray, 0, a.length); copy(elementsToAdd, 0, newArray, a.length, elementsToAdd.length); return newArray; } /** * Returns a new array with elements copied from the specified array and the specified elements added at the end. *
* The original array remains unchanged. * * @param a The first array whose elements are added to the new array. * @param elementsToAdd The additional elements to be added to the new array. * @return A new String array containing the elements from a and elementsToAdd. */ @SafeVarargs public static String[] addAll(final String[] a, final String... elementsToAdd) { if (isEmpty(a)) { return isEmpty(elementsToAdd) ? EMPTY_STRING_ARRAY : elementsToAdd.clone(); } final String[] newArray = new String[a.length + elementsToAdd.length]; copy(a, 0, newArray, 0, a.length); copy(elementsToAdd, 0, newArray, a.length, elementsToAdd.length); return newArray; } /** * Returns a new array with elements copied from the specified array and the specified elements added at the end. *
* The original array remains unchanged. * * @param The type of elements in the array. * @param a The original array. * @param elementsToAdd The elements to be added to the array. * @return A new array containing the original elements and the added elements. * @throws IllegalArgumentException if the input array a and elementsToAdd both are {@code null}. */ @SafeVarargs public static T[] addAll(@NotNull final T[] a, final T... elementsToAdd) throws IllegalArgumentException { checkArgNotNull(a, cs.a); if (isEmpty(a)) { return elementsToAdd == null ? a.clone() : elementsToAdd.clone(); } final T[] newArray = Array.newInstance(a.getClass().getComponentType(), a.length + elementsToAdd.length); copy(a, 0, newArray, 0, a.length); copy(elementsToAdd, 0, newArray, a.length, elementsToAdd.length); return newArray; } /** * Adds all the elements in elementsToAdd to the given collection. * * @param The type of elements in the collection. * @param c The original collection. * @param elementsToAdd The elements to be added to the collection. * @return A boolean indicating if the collection changed as a result of the call. * @throws IllegalArgumentException if the original collection is {@code null}. */ @SafeVarargs public static boolean addAll(@NotNull final Collection c, final T... elementsToAdd) throws IllegalArgumentException { checkArgNotNull(c, cs.c); if (isEmpty(elementsToAdd)) { return false; } return c.addAll(Array.asList(elementsToAdd)); } /** * Adds all the elements in elementsToAdd to the given collection. * * @param The type of elements in the collection. * @param c The original collection where elements are to be added. * @param elementsToAdd The collection of elements to be added to the original collection. * @return A boolean indicating if the original collection changed as a result of the call. * @throws IllegalArgumentException if the original collection is {@code null}. */ public static boolean addAll(@NotNull final Collection c, final Iterable elementsToAdd) throws IllegalArgumentException { checkArgNotNull(c, cs.c); if (elementsToAdd == null) { return false; } if (elementsToAdd instanceof final Collection coll) { // NOSONAR return c.addAll(coll); } else { return addAll(c, elementsToAdd.iterator()); } } /** * Adds all the elements in elementsToAdd to the given collection. * * @param The type of elements in the collection. * @param c The original collection where elements are to be added. * @param elementsToAdd The iterator of elements to be added to the original collection. * @return A boolean indicating if the original collection changed as a result of the call. * @throws IllegalArgumentException if the original collection is {@code null}. */ public static boolean addAll(@NotNull final Collection c, final Iterator elementsToAdd) throws IllegalArgumentException { checkArgNotNull(c, cs.c); if (elementsToAdd == null) { return false; } boolean wasModified = false; while (elementsToAdd.hasNext()) { wasModified |= c.add(elementsToAdd.next()); } return wasModified; } /** * Returns a new array with elements copied from the specified array and the specified element inserted at the specified index. *
* The original array remains unchanged. * * @param a the original boolean array * @param index the position in the array where the new element should be inserted * @param elementToInsert the char value to be inserted into the array * @return a new char array with the original elements and the inserted element * @throws IndexOutOfBoundsException if the specified index is out of range */ public static boolean[] insert(final boolean[] a, final int index, final boolean elementToInsert) throws IndexOutOfBoundsException { checkPositionIndex(index, len(a)); if (isEmpty(a) && index == 0) { return Array.of(elementToInsert); } final boolean[] newArray = new boolean[a.length + 1]; if (index > 0) { copy(a, 0, newArray, 0, index); } newArray[index] = elementToInsert; if (index < a.length) { copy(a, index, newArray, index + 1, a.length - index); } return newArray; } /** * Returns a new array with elements copied from the specified array and the specified element inserted at the specified index. *
* The original array remains unchanged. * * @param a the original char array * @param index the position in the array where the new element should be inserted * @param elementToInsert the boolean value to be inserted into the array * @return a new boolean array with the original elements and the inserted element * @throws IndexOutOfBoundsException if the specified index is out of range */ public static char[] insert(final char[] a, final int index, final char elementToInsert) throws IndexOutOfBoundsException { checkPositionIndex(index, len(a)); if (isEmpty(a) && index == 0) { return Array.of(elementToInsert); } final char[] newArray = new char[a.length + 1]; if (index > 0) { copy(a, 0, newArray, 0, index); } newArray[index] = elementToInsert; if (index < a.length) { copy(a, index, newArray, index + 1, a.length - index); } return newArray; } /** * Returns a new array with elements copied from the specified array and the specified element inserted at the specified index. *
* The original array remains unchanged. * * @param a the original byte array * @param index the position in the array where the new element should be inserted * @param elementToInsert the byte value to be inserted into the array * @return a new byte array with the original elements and the inserted element * @throws IndexOutOfBoundsException if the specified index is out of range */ public static byte[] insert(final byte[] a, final int index, final byte elementToInsert) throws IndexOutOfBoundsException { checkPositionIndex(index, len(a)); if (isEmpty(a) && index == 0) { return Array.of(elementToInsert); } final byte[] newArray = new byte[a.length + 1]; if (index > 0) { copy(a, 0, newArray, 0, index); } newArray[index] = elementToInsert; if (index < a.length) { copy(a, index, newArray, index + 1, a.length - index); } return newArray; } /** * Returns a new array with elements copied from the specified array and the specified element inserted at the specified index. *
* The original array remains unchanged. * * @param a the original short array * @param index the position in the array where the new element should be inserted * @param elementToInsert the short value to be inserted into the array * @return a new short array with the original elements and the inserted element * @throws IndexOutOfBoundsException if the specified index is out of range */ public static short[] insert(final short[] a, final int index, final short elementToInsert) throws IndexOutOfBoundsException { checkPositionIndex(index, len(a)); if (isEmpty(a) && index == 0) { return Array.of(elementToInsert); } final short[] newArray = new short[a.length + 1]; if (index > 0) { copy(a, 0, newArray, 0, index); } newArray[index] = elementToInsert; if (index < a.length) { copy(a, index, newArray, index + 1, a.length - index); } return newArray; } /** * Returns a new array with elements copied from the specified array and the specified element inserted at the specified index. *
* The original array remains unchanged. * * @param a the original int array * @param index the position in the array where the new element should be inserted * @param elementToInsert the int value to be inserted into the array * @return a new int array with the original elements and the inserted element * @throws IndexOutOfBoundsException if the specified index is out of range */ public static int[] insert(final int[] a, final int index, final int elementToInsert) throws IndexOutOfBoundsException { checkPositionIndex(index, len(a)); if (isEmpty(a) && index == 0) { return Array.of(elementToInsert); } final int[] newArray = new int[a.length + 1]; if (index > 0) { copy(a, 0, newArray, 0, index); } newArray[index] = elementToInsert; if (index < a.length) { copy(a, index, newArray, index + 1, a.length - index); } return newArray; } /** * Returns a new array with elements copied from the specified array and the specified element inserted at the specified index. *
* The original array remains unchanged. * * @param a the original long array * @param index the position in the array where the new element should be inserted * @param elementToInsert the long value to be inserted into the array * @return a new long array with the original elements and the inserted element * @throws IndexOutOfBoundsException if the specified index is out of range */ public static long[] insert(final long[] a, final int index, final long elementToInsert) throws IndexOutOfBoundsException { checkPositionIndex(index, len(a)); if (isEmpty(a) && index == 0) { return Array.of(elementToInsert); } final long[] newArray = new long[a.length + 1]; if (index > 0) { copy(a, 0, newArray, 0, index); } newArray[index] = elementToInsert; if (index < a.length) { copy(a, index, newArray, index + 1, a.length - index); } return newArray; } /** * Returns a new array with elements copied from the specified array and the specified element inserted at the specified index. *
* The original array remains unchanged. * * @param a the original float array * @param index the position in the array where the new element should be inserted * @param elementToInsert the float value to be inserted into the array * @return a new float array with the original elements and the inserted element * @throws IndexOutOfBoundsException if the specified index is out of range */ public static float[] insert(final float[] a, final int index, final float elementToInsert) throws IndexOutOfBoundsException { checkPositionIndex(index, len(a)); if (isEmpty(a) && index == 0) { return Array.of(elementToInsert); } final float[] newArray = new float[a.length + 1]; if (index > 0) { copy(a, 0, newArray, 0, index); } newArray[index] = elementToInsert; if (index < a.length) { copy(a, index, newArray, index + 1, a.length - index); } return newArray; } /** * Returns a new array with elements copied from the specified array and the specified element inserted at the specified index. *
* The original array remains unchanged. * * @param a the original double array * @param index the position in the array where the new element should be inserted * @param elementToInsert the double value to be inserted into the array * @return a new double array with the original elements and the inserted element * @throws IndexOutOfBoundsException if the specified index is out of range */ public static double[] insert(final double[] a, final int index, final double elementToInsert) throws IndexOutOfBoundsException { checkPositionIndex(index, len(a)); if (isEmpty(a) && index == 0) { return Array.of(elementToInsert); } final double[] newArray = new double[a.length + 1]; if (index > 0) { copy(a, 0, newArray, 0, index); } newArray[index] = elementToInsert; if (index < a.length) { copy(a, index, newArray, index + 1, a.length - index); } return newArray; } /** * Returns a new array with elements copied from the specified array and the specified element inserted at the specified index. *
* The original array remains unchanged. * * @param a the original String array * @param index the position in the array where the new element should be inserted * @param elementToInsert the String value to be inserted into the array * @return a new String array with the original elements and the inserted element * @throws IndexOutOfBoundsException if the specified index is out of range */ public static String[] insert(final String[] a, final int index, final String elementToInsert) throws IndexOutOfBoundsException { checkPositionIndex(index, len(a)); if (isEmpty(a) && index == 0) { return asArray(elementToInsert); } final String[] newArray = new String[a.length + 1]; if (index > 0) { copy(a, 0, newArray, 0, index); } newArray[index] = elementToInsert; if (index < a.length) { copy(a, index, newArray, index + 1, a.length - index); } return newArray; } /** * Returns a new array with elements copied from the specified array and the specified element inserted at the specified index. *
* The original array remains unchanged. * * @param the type of the elements in the array * @param a the original array * @param index the position in the array where the new element should be inserted * @param elementToInsert the element to be inserted into the array * @return a new array with the original elements and the inserted element * @throws IllegalArgumentException if the original array is {@code null} * @throws IndexOutOfBoundsException if the specified index is out of range */ public static T[] insert(@NotNull final T[] a, final int index, final T elementToInsert) throws IllegalArgumentException, IndexOutOfBoundsException { checkArgNotNull(a, cs.a); checkPositionIndex(index, len(a)); final T[] newArray = newArray(a.getClass().getComponentType(), a.length + 1); if (index > 0) { copy(a, 0, newArray, 0, index); } newArray[index] = elementToInsert; if (index < a.length) { copy(a, index, newArray, index + 1, a.length - index); } return newArray; } // /** // * // * @param // * @param list // * @param index // * @param elementToInsert // * @throws IllegalArgumentException // */ // public static void insert(@NotNull final List list, final int index, final T elementToInsert) throws IllegalArgumentException { // checkArgNotNull(list, "list"); // // list.add(index, elementToInsert); // } /** * Returns a new String with chars copied from the specified String and the specified String inserted at the specified index. *
* The original String remains unchanged. * * @param str the original string * @param index the position in the string where the new string should be inserted * @param strToInsert the string to be inserted into the original string * @return a new string with the original characters and the inserted string * @throws IndexOutOfBoundsException if the index is out of range (index < 0 || index > str.length()) */ public static String insert(final String str, final int index, final String strToInsert) throws IndexOutOfBoundsException { checkPositionIndex(index, len(str)); if (Strings.isEmpty(strToInsert)) { return Strings.nullToEmpty(str); } else if (Strings.isEmpty(str)) { return Strings.nullToEmpty(strToInsert); } else if (index == str.length()) { return Strings.concat(str + strToInsert); } return str; } /** * Returns a new array with elements copied from the specified array and the specified elements inserted at the specified index. *
* The original array remains unchanged. * * @param a the original array * @param index the position in the array where the new elements should be inserted * @param elementsToInsert the elements to be inserted into the array * @return a new array with the original elements and the inserted elements * @throws IndexOutOfBoundsException if the specified index is out of range */ @SafeVarargs public static boolean[] insertAll(final boolean[] a, final int index, final boolean... elementsToInsert) throws IndexOutOfBoundsException { checkPositionIndex(index, len(a)); if (isEmpty(a) && index == 0) { return elementsToInsert.clone(); } final boolean[] newArray = new boolean[a.length + elementsToInsert.length]; if (index > 0) { copy(a, 0, newArray, 0, index); } copy(elementsToInsert, 0, newArray, index, elementsToInsert.length); if (index < a.length) { copy(a, index, newArray, index + elementsToInsert.length, a.length - index); } return newArray; } /** * Returns a new array with elements copied from the specified array and the specified elements inserted at the specified index. *
* The original array remains unchanged. * * @param a the original array * @param index the position in the array where the new elements should be inserted * @param elementsToInsert the elements to be inserted into the array * @return a new array with the original elements and the inserted elements * @throws IndexOutOfBoundsException if the specified index is out of range */ @SafeVarargs public static char[] insertAll(final char[] a, final int index, final char... elementsToInsert) throws IndexOutOfBoundsException { checkPositionIndex(index, len(a)); if (isEmpty(a) && index == 0) { return elementsToInsert.clone(); } final char[] newArray = new char[a.length + elementsToInsert.length]; if (index > 0) { copy(a, 0, newArray, 0, index); } copy(elementsToInsert, 0, newArray, index, elementsToInsert.length); if (index < a.length) { copy(a, index, newArray, index + elementsToInsert.length, a.length - index); } return newArray; } /** * Returns a new array with elements copied from the specified array and the specified elements inserted at the specified index. *
* The original array remains unchanged. * * @param a the original array * @param index the position in the array where the new elements should be inserted * @param elementsToInsert the elements to be inserted into the array * @return a new array with the original elements and the inserted elements * @throws IndexOutOfBoundsException if the specified index is out of range */ @SafeVarargs public static byte[] insertAll(final byte[] a, final int index, final byte... elementsToInsert) throws IndexOutOfBoundsException { checkPositionIndex(index, len(a)); if (isEmpty(a) && index == 0) { return elementsToInsert.clone(); } final byte[] newArray = new byte[a.length + elementsToInsert.length]; if (index > 0) { copy(a, 0, newArray, 0, index); } copy(elementsToInsert, 0, newArray, index, elementsToInsert.length); if (index < a.length) { copy(a, index, newArray, index + elementsToInsert.length, a.length - index); } return newArray; } /** * Returns a new array with elements copied from the specified array and the specified elements inserted at the specified index. *
* The original array remains unchanged. * * @param a the original array * @param index the position in the array where the new elements should be inserted * @param elementsToInsert the elements to be inserted into the array * @return a new array with the original elements and the inserted elements * @throws IndexOutOfBoundsException if the specified index is out of range */ @SafeVarargs public static short[] insertAll(final short[] a, final int index, final short... elementsToInsert) throws IndexOutOfBoundsException { checkPositionIndex(index, len(a)); if (isEmpty(a) && index == 0) { return elementsToInsert.clone(); } final short[] newArray = new short[a.length + elementsToInsert.length]; if (index > 0) { copy(a, 0, newArray, 0, index); } copy(elementsToInsert, 0, newArray, index, elementsToInsert.length); if (index < a.length) { copy(a, index, newArray, index + elementsToInsert.length, a.length - index); } return newArray; } /** * Returns a new array with elements copied from the specified array and the specified elements inserted at the specified index. *
* The original array remains unchanged. * * @param a the original array * @param index the position in the array where the new elements should be inserted * @param elementsToInsert the elements to be inserted into the array * @return a new array with the original elements and the inserted elements * @throws IndexOutOfBoundsException if the specified index is out of range */ @SafeVarargs public static int[] insertAll(final int[] a, final int index, final int... elementsToInsert) throws IndexOutOfBoundsException { checkPositionIndex(index, len(a)); if (isEmpty(a) && index == 0) { return elementsToInsert.clone(); } final int[] newArray = new int[a.length + elementsToInsert.length]; if (index > 0) { copy(a, 0, newArray, 0, index); } copy(elementsToInsert, 0, newArray, index, elementsToInsert.length); if (index < a.length) { copy(a, index, newArray, index + elementsToInsert.length, a.length - index); } return newArray; } /** * Returns a new array with elements copied from the specified array and the specified elements inserted at the specified index. *
* The original array remains unchanged. * * @param a the original array * @param index the position in the array where the new elements should be inserted * @param elementsToInsert the elements to be inserted into the array * @return a new array with the original elements and the inserted elements * @throws IndexOutOfBoundsException if the specified index is out of range */ @SafeVarargs public static long[] insertAll(final long[] a, final int index, final long... elementsToInsert) throws IndexOutOfBoundsException { checkPositionIndex(index, len(a)); if (isEmpty(a) && index == 0) { return elementsToInsert.clone(); } final long[] newArray = new long[a.length + elementsToInsert.length]; if (index > 0) { copy(a, 0, newArray, 0, index); } copy(elementsToInsert, 0, newArray, index, elementsToInsert.length); if (index < a.length) { copy(a, index, newArray, index + elementsToInsert.length, a.length - index); } return newArray; } /** * Returns a new array with elements copied from the specified array and the specified elements inserted at the specified index. *
* The original array remains unchanged. * * @param a the original array * @param index the position in the array where the new elements should be inserted * @param elementsToInsert the elements to be inserted into the array * @return a new array with the original elements and the inserted elements * @throws IndexOutOfBoundsException if the specified index is out of range */ @SafeVarargs public static float[] insertAll(final float[] a, final int index, final float... elementsToInsert) throws IndexOutOfBoundsException { checkPositionIndex(index, len(a)); if (isEmpty(a) && index == 0) { return elementsToInsert.clone(); } final float[] newArray = new float[a.length + elementsToInsert.length]; if (index > 0) { copy(a, 0, newArray, 0, index); } copy(elementsToInsert, 0, newArray, index, elementsToInsert.length); if (index < a.length) { copy(a, index, newArray, index + elementsToInsert.length, a.length - index); } return newArray; } /** * Returns a new array with elements copied from the specified array and the specified elements inserted at the specified index. *
* The original array remains unchanged. * * @param a the original array * @param index the position in the array where the new elements should be inserted * @param elementsToInsert the elements to be inserted into the array * @return a new array with the original elements and the inserted elements * @throws IndexOutOfBoundsException if the specified index is out of range */ @SafeVarargs public static double[] insertAll(final double[] a, final int index, final double... elementsToInsert) throws IndexOutOfBoundsException { checkPositionIndex(index, len(a)); if (isEmpty(a) && index == 0) { return elementsToInsert.clone(); } final double[] newArray = new double[a.length + elementsToInsert.length]; if (index > 0) { copy(a, 0, newArray, 0, index); } copy(elementsToInsert, 0, newArray, index, elementsToInsert.length); if (index < a.length) { copy(a, index, newArray, index + elementsToInsert.length, a.length - index); } return newArray; } /** * Returns a new array with elements copied from the specified array and the specified elements inserted at the specified index. *
* The original array remains unchanged. * * @param a the original array * @param index the position in the array where the new elements should be inserted * @param elementsToInsert the elements to be inserted into the array * @return a new array with the original elements and the inserted elements * @throws IndexOutOfBoundsException if the specified index is out of range */ @SafeVarargs public static String[] insertAll(final String[] a, final int index, final String... elementsToInsert) throws IndexOutOfBoundsException { checkPositionIndex(index, len(a)); if (isEmpty(a) && index == 0) { return elementsToInsert.clone(); } final String[] newArray = new String[a.length + elementsToInsert.length]; if (index > 0) { copy(a, 0, newArray, 0, index); } copy(elementsToInsert, 0, newArray, index, elementsToInsert.length); if (index < a.length) { copy(a, index, newArray, index + elementsToInsert.length, a.length - index); } return newArray; } /** * Returns a new array with elements copied from the specified array and the specified elements inserted at the specified index. *
* The original array remains unchanged. * * @param a the original array * @param index the position in the array where the new elements should be inserted * @param elementsToInsert the elements to be inserted into the array * @return a new array with the original elements and the inserted elements * @throws IllegalArgumentException if the specified {@code Array} is {@code null}. * @throws IndexOutOfBoundsException if the specified index is out of range */ @SafeVarargs public static T[] insertAll(@NotNull final T[] a, final int index, final T... elementsToInsert) throws IllegalArgumentException, IndexOutOfBoundsException { checkArgNotNull(a, cs.a); checkPositionIndex(index, len(a)); final T[] newArray = Array.newInstance(a.getClass().getComponentType(), a.length + elementsToInsert.length); if (index > 0) { copy(a, 0, newArray, 0, index); } copy(elementsToInsert, 0, newArray, index, elementsToInsert.length); if (index < a.length) { copy(a, index, newArray, index + elementsToInsert.length, a.length - index); } return newArray; } /** * Inserts the specified elements at the specified position in the list. * Shifts the element currently at that position (if any) and any subsequent elements to the right (adds one to their indices). * * @param the type of elements in the list * @param list the list to insert into * @param index the position in the list where the new elements should be inserted * @param elementsToInsert the elements to be inserted into the list * @return {@code true} if the list changed as a result of the call * @throws IllegalArgumentException if the list is {@code null} * @throws IndexOutOfBoundsException if the index is out of range (index < 0 || index > list.size()) */ @SafeVarargs public static boolean insertAll(@NotNull final List list, final int index, final T... elementsToInsert) throws IllegalArgumentException, IndexOutOfBoundsException { checkArgNotNull(list, cs.list); checkPositionIndex(index, size(list)); if (isEmpty(elementsToInsert)) { return false; } return list.addAll(index, asList(elementsToInsert)); } /** * Inserts the specified elements at the specified position in the list. * Shifts the element currently at that position (if any) and any subsequent elements to the right (adds one to their indices). * * @param the type of elements in the list * @param list the list to insert into * @param index the position in the list where the new elements should be inserted * @param elementsToInsert the elements to be inserted into the list * @return {@code true} if the list changed as a result of the call * @throws IllegalArgumentException if the list is {@code null} * @throws IndexOutOfBoundsException if the index is out of range (index < 0 || index > list.size()) */ public static boolean insertAll(@NotNull final List list, final int index, final Collection elementsToInsert) throws IllegalArgumentException, IndexOutOfBoundsException { checkArgNotNull(list, cs.list); checkPositionIndex(index, size(list)); if (isEmpty(elementsToInsert)) { return false; } return list.addAll(index, elementsToInsert); } /** * Returns a new array with elements copied from the specified array except the element at the specified position. *
* The original array remains unchanged. * * @param a the original boolean array * @param index the position of the element to be removed * @return a new boolean array containing the existing elements except the element at the specified index * @throws IndexOutOfBoundsException if the specified index is out of range */ public static boolean[] deleteByIndex(@NotNull final boolean[] a, final int index) throws IllegalArgumentException, IndexOutOfBoundsException { // checkArgNotNull(a, cs.a); checkElementIndex(index, len(a)); if (isEmpty(a)) { return EMPTY_BOOLEAN_ARRAY; } final boolean[] result = new boolean[a.length - 1]; if (index > 0) { copy(a, 0, result, 0, index); } if (index + 1 < a.length) { copy(a, index + 1, result, index, a.length - index - 1); } return result; } /** * Returns a new array with elements copied from the specified array except the element at the specified position. *
* The original array remains unchanged. * * @param a the original char array * @param index the position of the element to be removed * @return a new char array containing the existing elements except the element at the specified index * @throws IndexOutOfBoundsException if the specified index is out of range */ public static char[] deleteByIndex(@NotNull final char[] a, final int index) throws IllegalArgumentException, IndexOutOfBoundsException { // checkArgNotNull(a, cs.a); checkElementIndex(index, len(a)); if (isEmpty(a)) { return EMPTY_CHAR_ARRAY; } final char[] result = new char[a.length - 1]; if (index > 0) { copy(a, 0, result, 0, index); } if (index + 1 < a.length) { copy(a, index + 1, result, index, a.length - index - 1); } return result; } /** * Returns a new array with elements copied from the specified array except the element at the specified position. *
* The original array remains unchanged. * * @param a the original byte array * @param index the position of the element to be removed * @return a new byte array containing the existing elements except the element at the specified index * @throws IndexOutOfBoundsException if the specified index is out of range */ public static byte[] deleteByIndex(@NotNull final byte[] a, final int index) throws IllegalArgumentException, IndexOutOfBoundsException { // checkArgNotNull(a, cs.a); checkElementIndex(index, len(a)); if (isEmpty(a)) { return EMPTY_BYTE_ARRAY; } final byte[] result = new byte[a.length - 1]; if (index > 0) { copy(a, 0, result, 0, index); } if (index + 1 < a.length) { copy(a, index + 1, result, index, a.length - index - 1); } return result; } /** * Returns a new array with elements copied from the specified array except the element at the specified position. *
* The original array remains unchanged. * * @param a the original short array * @param index the position of the element to be removed * @return a new short array containing the existing elements except the element at the specified index * @throws IndexOutOfBoundsException if the specified index is out of range */ public static short[] deleteByIndex(@NotNull final short[] a, final int index) throws IllegalArgumentException, IndexOutOfBoundsException { // checkArgNotNull(a, cs.a); checkElementIndex(index, len(a)); if (isEmpty(a)) { return EMPTY_SHORT_ARRAY; } final short[] result = new short[a.length - 1]; if (index > 0) { copy(a, 0, result, 0, index); } if (index + 1 < a.length) { copy(a, index + 1, result, index, a.length - index - 1); } return result; } /** * Returns a new array with elements copied from the specified array except the element at the specified position. *
* The original array remains unchanged. * * @param a the original int array * @param index the position of the element to be removed * @return a new int array containing the existing elements except the element at the specified index * @throws IndexOutOfBoundsException if the specified index is out of range */ public static int[] deleteByIndex(@NotNull final int[] a, final int index) throws IllegalArgumentException, IndexOutOfBoundsException { // checkArgNotNull(a, cs.a); checkElementIndex(index, len(a)); if (isEmpty(a)) { return EMPTY_INT_ARRAY; } final int[] result = new int[a.length - 1]; if (index > 0) { copy(a, 0, result, 0, index); } if (index + 1 < a.length) { copy(a, index + 1, result, index, a.length - index - 1); } return result; } /** * Returns a new array with elements copied from the specified array except the element at the specified position. *
* The original array remains unchanged. * * @param a the original long array * @param index the position of the element to be removed * @return a new long array containing the existing elements except the element at the specified index * @throws IndexOutOfBoundsException if the specified index is out of range */ public static long[] deleteByIndex(@NotNull final long[] a, final int index) throws IllegalArgumentException, IndexOutOfBoundsException { // checkArgNotNull(a, cs.a); checkElementIndex(index, len(a)); if (isEmpty(a)) { return EMPTY_LONG_ARRAY; } final long[] result = new long[a.length - 1]; if (index > 0) { copy(a, 0, result, 0, index); } if (index + 1 < a.length) { copy(a, index + 1, result, index, a.length - index - 1); } return result; } /** * Returns a new array with elements copied from the specified array except the element at the specified position. *
* The original array remains unchanged. * * @param a the original float array * @param index the position of the element to be removed * @return a new float array containing the existing elements except the element at the specified index * @throws IndexOutOfBoundsException if the specified index is out of range */ public static float[] deleteByIndex(@NotNull final float[] a, final int index) throws IllegalArgumentException, IndexOutOfBoundsException { // checkArgNotNull(a, cs.a); checkElementIndex(index, len(a)); if (isEmpty(a)) { return EMPTY_FLOAT_ARRAY; } final float[] result = new float[a.length - 1]; if (index > 0) { copy(a, 0, result, 0, index); } if (index + 1 < a.length) { copy(a, index + 1, result, index, a.length - index - 1); } return result; } /** * Returns a new array with elements copied from the specified array except the element at the specified position. *
* The original array remains unchanged. * * @param a the original double array * @param index the position of the element to be removed * @return a new double array containing the existing elements except the element at the specified index * @throws IndexOutOfBoundsException if the specified index is out of range */ public static double[] deleteByIndex(@NotNull final double[] a, final int index) throws IllegalArgumentException, IndexOutOfBoundsException { // checkArgNotNull(a, cs.a); checkElementIndex(index, len(a)); if (isEmpty(a)) { return EMPTY_DOUBLE_ARRAY; } final double[] result = new double[a.length - 1]; if (index > 0) { copy(a, 0, result, 0, index); } if (index + 1 < a.length) { copy(a, index + 1, result, index, a.length - index - 1); } return result; } /** * Returns a new array with elements copied from the specified array except the element at the specified position. *
* The original array remains unchanged. * * @param a the original array * @param index the position of the element to be removed * @return a new array containing the existing elements except the element at the specified index * @throws IndexOutOfBoundsException if the specified index is out of range */ public static T[] deleteByIndex(@NotNull final T[] a, final int index) throws IllegalArgumentException, IndexOutOfBoundsException { // checkArgNotNull(a, cs.a); checkElementIndex(index, len(a)); if (isEmpty(a)) { return a; } final T[] result = newArray(a.getClass().getComponentType(), a.length - 1); if (index > 0) { copy(a, 0, result, 0, index); } if (index + 1 < a.length) { copy(a, index + 1, result, index, a.length - index - 1); } return result; } // /** // * // * @param // * @param list // * @param index // * @return // * @throws IllegalArgumentException // */ // public static T delete(@NotNull final List list, final int index) throws IllegalArgumentException { // checkArgNotNull(list, "list"); // // return list.remove(index); // } /** * Returns a new array with elements copied from the specified array except the elements at the specified positions. *
* The original array remains unchanged. * * @param a the input boolean array from which elements are to be removed * @param indices the positions of the elements to be removed * @return a new boolean array containing the remaining elements after removal * @throws IndexOutOfBoundsException if any index is out of the array's range */ @SafeVarargs public static boolean[] deleteAllByIndices(final boolean[] a, int... indices) throws IndexOutOfBoundsException { final int countOfIndex = indices.length; if (isEmpty(indices)) { return a == null ? EMPTY_BOOLEAN_ARRAY : a.clone(); } else if (countOfIndex == 1) { return deleteByIndex(a, indices[0]); } indices = indices.clone(); sort(indices); final int lastIndex = indices[countOfIndex - 1]; final int arrayLen = a.length; if (indices[0] < 0 || lastIndex >= arrayLen) { throw new IndexOutOfBoundsException("The specified indices are from: " + indices[0] + " to: " + lastIndex); //NOSONAR } int diff = 1; for (int i = 1; i < countOfIndex; i++) { if (indices[i] == indices[i - 1]) { continue; } diff++; } final boolean[] result = new boolean[arrayLen - diff]; int dest = 0; int len = 0; for (int i = 0, preIndex = -1; i < countOfIndex; preIndex = indices[i], i++) { if (indices[i] - preIndex > 1) { len = indices[i] - preIndex - 1; copy(a, preIndex + 1, result, dest, len); dest += len; } } if (lastIndex < arrayLen - 1) { len = arrayLen - lastIndex - 1; copy(a, lastIndex + 1, result, dest, len); } return result; } /** * Returns a new array with elements copied from the specified array except the elements at the specified positions. *
* The original array remains unchanged. * * @param a the input char array from which elements are to be removed * @param indices the positions of the elements to be removed * @return a new char array containing the remaining elements after removal * @throws IndexOutOfBoundsException if any index is out of the array's range */ @SafeVarargs public static char[] deleteAllByIndices(final char[] a, int... indices) throws IndexOutOfBoundsException { final int countOfIndex = indices.length; if (isEmpty(indices)) { return a == null ? EMPTY_CHAR_ARRAY : a.clone(); } else if (countOfIndex == 1) { return deleteByIndex(a, indices[0]); } indices = indices.clone(); sort(indices); final int lastIndex = indices[countOfIndex - 1]; final int arrayLen = a.length; if (indices[0] < 0 || lastIndex >= arrayLen) { throw new IndexOutOfBoundsException("The specified indices are from: " + indices[0] + " to: " + lastIndex); //NOSONAR } int diff = 1; for (int i = 1; i < countOfIndex; i++) { if (indices[i] == indices[i - 1]) { continue; } diff++; } final char[] result = new char[arrayLen - diff]; int dest = 0; int len = 0; for (int i = 0, preIndex = -1; i < countOfIndex; preIndex = indices[i], i++) { if (indices[i] - preIndex > 1) { len = indices[i] - preIndex - 1; copy(a, preIndex + 1, result, dest, len); dest += len; } } if (lastIndex < arrayLen - 1) { len = arrayLen - lastIndex - 1; copy(a, lastIndex + 1, result, dest, len); } return result; } /** * Returns a new array with elements copied from the specified array except the elements at the specified positions. *
* The original array remains unchanged. * * @param a the input byte array from which elements are to be removed * @param indices the positions of the elements to be removed * @return a new byte array containing the remaining elements after removal * @throws IndexOutOfBoundsException if any index is out of the array's range */ @SafeVarargs public static byte[] deleteAllByIndices(final byte[] a, int... indices) throws IndexOutOfBoundsException { final int countOfIndex = indices.length; if (isEmpty(indices)) { return a == null ? EMPTY_BYTE_ARRAY : a.clone(); } else if (countOfIndex == 1) { return deleteByIndex(a, indices[0]); } indices = indices.clone(); sort(indices); final int lastIndex = indices[countOfIndex - 1]; final int arrayLen = a.length; if (indices[0] < 0 || lastIndex >= arrayLen) { throw new IndexOutOfBoundsException("The specified indices are from: " + indices[0] + " to: " + lastIndex); //NOSONAR } int diff = 1; for (int i = 1; i < countOfIndex; i++) { if (indices[i] == indices[i - 1]) { continue; } diff++; } final byte[] result = new byte[arrayLen - diff]; int dest = 0; int len = 0; for (int i = 0, preIndex = -1; i < countOfIndex; preIndex = indices[i], i++) { if (indices[i] - preIndex > 1) { len = indices[i] - preIndex - 1; copy(a, preIndex + 1, result, dest, len); dest += len; } } if (lastIndex < arrayLen - 1) { len = arrayLen - lastIndex - 1; copy(a, lastIndex + 1, result, dest, len); } return result; } /** * Returns a new array with elements copied from the specified array except the elements at the specified positions. *
* The original array remains unchanged. * * @param a the input short array from which elements are to be removed * @param indices the positions of the elements to be removed * @return a new short array containing the remaining elements after removal * @throws IndexOutOfBoundsException if any index is out of the array's range */ @SafeVarargs public static short[] deleteAllByIndices(final short[] a, int... indices) throws IndexOutOfBoundsException { final int countOfIndex = indices.length; if (isEmpty(indices)) { return a == null ? EMPTY_SHORT_ARRAY : a.clone(); } else if (countOfIndex == 1) { return deleteByIndex(a, indices[0]); } indices = indices.clone(); sort(indices); final int lastIndex = indices[countOfIndex - 1]; final int arrayLen = a.length; if (indices[0] < 0 || lastIndex >= arrayLen) { throw new IndexOutOfBoundsException("The specified indices are from: " + indices[0] + " to: " + lastIndex); //NOSONAR } int diff = 1; for (int i = 1; i < countOfIndex; i++) { if (indices[i] == indices[i - 1]) { continue; } diff++; } final short[] result = new short[arrayLen - diff]; int dest = 0; int len = 0; for (int i = 0, preIndex = -1; i < countOfIndex; preIndex = indices[i], i++) { if (indices[i] - preIndex > 1) { len = indices[i] - preIndex - 1; copy(a, preIndex + 1, result, dest, len); dest += len; } } if (lastIndex < arrayLen - 1) { len = arrayLen - lastIndex - 1; copy(a, lastIndex + 1, result, dest, len); } return result; } /** * Returns a new array with elements copied from the specified array except the elements at the specified positions. *
* The original array remains unchanged. * * @param a the input int array from which elements are to be removed * @param indices the positions of the elements to be removed * @return a new int array containing the remaining elements after removal * @throws IndexOutOfBoundsException if any index is out of the array's range */ @SafeVarargs public static int[] deleteAllByIndices(final int[] a, int... indices) throws IndexOutOfBoundsException { final int countOfIndex = indices.length; if (isEmpty(indices)) { return a == null ? EMPTY_INT_ARRAY : a.clone(); } else if (countOfIndex == 1) { return deleteByIndex(a, indices[0]); } indices = indices.clone(); sort(indices); final int lastIndex = indices[countOfIndex - 1]; final int arrayLen = a.length; if (indices[0] < 0 || lastIndex >= arrayLen) { throw new IndexOutOfBoundsException("The specified indices are from: " + indices[0] + " to: " + lastIndex); //NOSONAR } int diff = 1; for (int i = 1; i < countOfIndex; i++) { if (indices[i] == indices[i - 1]) { continue; } diff++; } final int[] result = new int[arrayLen - diff]; int dest = 0; int len = 0; for (int i = 0, preIndex = -1; i < countOfIndex; preIndex = indices[i], i++) { if (indices[i] - preIndex > 1) { len = indices[i] - preIndex - 1; copy(a, preIndex + 1, result, dest, len); dest += len; } } if (lastIndex < arrayLen - 1) { len = arrayLen - lastIndex - 1; copy(a, lastIndex + 1, result, dest, len); } return result; } /** * Returns a new array with elements copied from the specified array except the elements at the specified positions. *
* The original array remains unchanged. * * @param a the input long array from which elements are to be removed * @param indices the positions of the elements to be removed * @return a new long array containing the remaining elements after removal * @throws IndexOutOfBoundsException if any index is out of the array's range */ @SafeVarargs public static long[] deleteAllByIndices(final long[] a, int... indices) throws IndexOutOfBoundsException { final int countOfIndex = indices.length; if (isEmpty(indices)) { return a == null ? EMPTY_LONG_ARRAY : a.clone(); } else if (countOfIndex == 1) { return deleteByIndex(a, indices[0]); } indices = indices.clone(); sort(indices); final int lastIndex = indices[countOfIndex - 1]; final int arrayLen = a.length; if (indices[0] < 0 || lastIndex >= arrayLen) { throw new IndexOutOfBoundsException("The specified indices are from: " + indices[0] + " to: " + lastIndex); //NOSONAR } int diff = 1; for (int i = 1; i < countOfIndex; i++) { if (indices[i] == indices[i - 1]) { continue; } diff++; } final long[] result = new long[arrayLen - diff]; int dest = 0; int len = 0; for (int i = 0, preIndex = -1; i < countOfIndex; preIndex = indices[i], i++) { if (indices[i] - preIndex > 1) { len = indices[i] - preIndex - 1; copy(a, preIndex + 1, result, dest, len); dest += len; } } if (lastIndex < arrayLen - 1) { len = arrayLen - lastIndex - 1; copy(a, lastIndex + 1, result, dest, len); } return result; } /** * Returns a new array with elements copied from the specified array except the elements at the specified positions. *
* The original array remains unchanged. * * @param a the input float array from which elements are to be removed * @param indices the positions of the elements to be removed * @return a new float array containing the remaining elements after removal * @throws IndexOutOfBoundsException if any index is out of the array's range */ @SafeVarargs public static float[] deleteAllByIndices(final float[] a, int... indices) throws IndexOutOfBoundsException { final int countOfIndex = indices.length; if (isEmpty(indices)) { return a == null ? EMPTY_FLOAT_ARRAY : a.clone(); } else if (countOfIndex == 1) { return deleteByIndex(a, indices[0]); } indices = indices.clone(); sort(indices); final int lastIndex = indices[countOfIndex - 1]; final int arrayLen = a.length; if (indices[0] < 0 || lastIndex >= arrayLen) { throw new IndexOutOfBoundsException("The specified indices are from: " + indices[0] + " to: " + lastIndex); //NOSONAR } int diff = 1; for (int i = 1; i < countOfIndex; i++) { if (indices[i] == indices[i - 1]) { continue; } diff++; } final float[] result = new float[arrayLen - diff]; int dest = 0; int len = 0; for (int i = 0, preIndex = -1; i < countOfIndex; preIndex = indices[i], i++) { if (indices[i] - preIndex > 1) { len = indices[i] - preIndex - 1; copy(a, preIndex + 1, result, dest, len); dest += len; } } if (lastIndex < arrayLen - 1) { len = arrayLen - lastIndex - 1; copy(a, lastIndex + 1, result, dest, len); } return result; } /** * Returns a new array with elements copied from the specified array except the elements at the specified positions. *
* The original array remains unchanged. * * @param a the input double array from which elements are to be removed * @param indices the positions of the elements to be removed * @return a new double array containing the remaining elements after removal * @throws IndexOutOfBoundsException if any index is out of the array's range */ @SafeVarargs public static double[] deleteAllByIndices(final double[] a, int... indices) throws IndexOutOfBoundsException { final int countOfIndex = indices.length; if (isEmpty(indices)) { return a == null ? EMPTY_DOUBLE_ARRAY : a.clone(); } else if (countOfIndex == 1) { return deleteByIndex(a, indices[0]); } indices = indices.clone(); sort(indices); final int lastIndex = indices[countOfIndex - 1]; final int arrayLen = a.length; if (indices[0] < 0 || lastIndex >= arrayLen) { throw new IndexOutOfBoundsException("The specified indices are from: " + indices[0] + " to: " + lastIndex); //NOSONAR } int diff = 1; for (int i = 1; i < countOfIndex; i++) { if (indices[i] == indices[i - 1]) { continue; } diff++; } final double[] result = new double[arrayLen - diff]; int dest = 0; int len = 0; for (int i = 0, preIndex = -1; i < countOfIndex; preIndex = indices[i], i++) { if (indices[i] - preIndex > 1) { len = indices[i] - preIndex - 1; copy(a, preIndex + 1, result, dest, len); dest += len; } } if (lastIndex < arrayLen - 1) { len = arrayLen - lastIndex - 1; copy(a, lastIndex + 1, result, dest, len); } return result; } /** * Returns a new array with elements copied from the specified array except the elements at the specified positions. *
* The original array remains unchanged. * * @param a the input String array from which elements are to be removed * @param indices the positions of the elements to be removed * @return a new String array containing the remaining elements after removal * @throws IndexOutOfBoundsException if any index is out of the array's range */ @SafeVarargs public static String[] deleteAllByIndices(final String[] a, int... indices) throws IndexOutOfBoundsException { if (isEmpty(indices)) { return a == null ? EMPTY_STRING_ARRAY : a.clone(); } else if (indices.length == 1) { return deleteByIndex(a, indices[0]); } indices = indices.clone(); sort(indices); return deleteAllBySortedIndices(a, indices); } /** * Returns a new array with elements copied from the specified array except the elements at the specified positions. *
* The original array remains unchanged. * * @param the type of elements in the input array * @param a the input array from which elements are to be removed * @param indices the positions of the elements to be removed * @return a new array containing the remaining elements after removal * @throws IndexOutOfBoundsException if any index is out of the array's range */ @SafeVarargs public static T[] deleteAllByIndices(@NotNull final T[] a, int... indices) throws IllegalArgumentException, IndexOutOfBoundsException { // checkArgNotNull(a, cs.a); if (isEmpty(indices)) { return isEmpty(a) ? a : a.clone(); } else if (indices.length == 1) { return deleteByIndex(a, indices[0]); } indices = indices.clone(); sort(indices); return deleteAllBySortedIndices(a, indices); } private static T[] deleteAllBySortedIndices(final T[] a, final int[] indices) throws IndexOutOfBoundsException { final int countOfIndex = indices.length; final int lastIndex = indices[countOfIndex - 1]; final int arrayLen = a.length; if (indices[0] < 0 || lastIndex >= arrayLen) { throw new IndexOutOfBoundsException("The specified indices are from: " + indices[0] + " to: " + lastIndex); } int diff = 1; for (int i = 1; i < countOfIndex; i++) { if (indices[i] == indices[i - 1]) { continue; } diff++; } final T[] result = newArray(a.getClass().getComponentType(), arrayLen - diff); int dest = 0; int len = 0; for (int i = 0, preIndex = -1; i < countOfIndex; preIndex = indices[i], i++) { if (indices[i] - preIndex > 1) { len = indices[i] - preIndex - 1; copy(a, preIndex + 1, result, dest, len); dest += len; } } if (lastIndex < arrayLen - 1) { len = arrayLen - lastIndex - 1; copy(a, lastIndex + 1, result, dest, len); } return result; } /** * Deletes all elements at the specified positions from the given list. * * @param list The list from which elements are to be removed. * @param indices The positions of the elements to be removed. * @return {@code true} if the list was modified as a result of the operation, {@code false} otherwise. * @throws IllegalArgumentException if the input list is {@code null}. */ @SuppressWarnings("rawtypes") @SafeVarargs public static boolean deleteAllByIndices(@NotNull final List list, int... indices) throws IllegalArgumentException { checkArgNotNull(list); if (isEmpty(indices)) { return false; } else if (indices.length == 1) { list.remove(indices[0]); return true; } indices = indices.clone(); sort(indices); if (indices[0] < 0 || indices[indices.length - 1] >= list.size()) { throw new IndexOutOfBoundsException("The specified indices are from: " + indices[0] + " to: " + indices[indices.length - 1]); } if (list instanceof LinkedList) { final Iterator iterator = list.iterator(); int idx = -1; for (int i = 0, len = indices.length; i < len; i++) { if (i > 0 && indices[i] == indices[i - 1]) { continue; } while (idx < indices[i]) { idx++; iterator.next(); } iterator.remove(); } } else { final Object[] a = list.toArray(); final Object[] res = deleteAllBySortedIndices(a, indices); list.clear(); list.addAll((List) Arrays.asList(res)); } return true; } /** * Returns a new array with elements copied from the specified array except the first occurrence of the specified value. *
* The original array remains unchanged. * * @param a The array from which the value should be removed. * @param valueToRemove The value to be removed from the array. * @return A new array with the first occurrence of the specified value removed. An empty array is returned if the specified array is {@code null} or empty. */ public static boolean[] remove(final boolean[] a, final boolean valueToRemove) { if (isEmpty(a)) { return EMPTY_BOOLEAN_ARRAY; } final int index = indexOf(a, valueToRemove, 0); return index == INDEX_NOT_FOUND ? a.clone() : deleteByIndex(a, index); } /** * Returns a new array with elements copied from the specified array except the first occurrence of the specified value. *
* The original array remains unchanged. * * @param a The array from which the value should be removed. * @param valueToRemove The value to be removed from the array. * @return A new array with the first occurrence of the specified value removed. An empty array is returned if the specified array is {@code null} or empty. */ public static char[] remove(final char[] a, final char valueToRemove) { if (isEmpty(a)) { return EMPTY_CHAR_ARRAY; } final int index = indexOf(a, valueToRemove, 0); return index == INDEX_NOT_FOUND ? a.clone() : deleteByIndex(a, index); } /** * Returns a new array with elements copied from the specified array except the first occurrence of the specified value. *
* The original array remains unchanged. * * @param a The array from which the value should be removed. * @param valueToRemove The value to be removed from the array. * @return A new array with the first occurrence of the specified value removed. An empty array is returned if the specified array is {@code null} or empty. */ public static byte[] remove(final byte[] a, final byte valueToRemove) { if (isEmpty(a)) { return EMPTY_BYTE_ARRAY; } final int index = indexOf(a, valueToRemove, 0); return index == INDEX_NOT_FOUND ? a.clone() : deleteByIndex(a, index); } /** * Returns a new array with elements copied from the specified array except the first occurrence of the specified value. *
* The original array remains unchanged. * * @param a The array from which the value should be removed. * @param valueToRemove The value to be removed from the array. * @return A new array with the first occurrence of the specified value removed. An empty array is returned if the specified array is {@code null} or empty. */ public static short[] remove(final short[] a, final short valueToRemove) { if (isEmpty(a)) { return EMPTY_SHORT_ARRAY; } final int index = indexOf(a, valueToRemove, 0); return index == INDEX_NOT_FOUND ? a.clone() : deleteByIndex(a, index); } /** * Returns a new array with elements copied from the specified array except the first occurrence of the specified value. *
* The original array remains unchanged. * * @param a The array from which the value should be removed. * @param valueToRemove The value to be removed from the array. * @return A new array with the first occurrence of the specified value removed. An empty array is returned if the specified array is {@code null} or empty. */ public static int[] remove(final int[] a, final int valueToRemove) { if (isEmpty(a)) { return EMPTY_INT_ARRAY; } final int index = indexOf(a, valueToRemove, 0); return index == INDEX_NOT_FOUND ? a.clone() : deleteByIndex(a, index); } /** * Returns a new array with elements copied from the specified array except the first occurrence of the specified value. *
* The original array remains unchanged. * * @param a The array from which the value should be removed. * @param valueToRemove The value to be removed from the array. * @return A new array with the first occurrence of the specified value removed. An empty array is returned if the specified array is {@code null} or empty. */ public static long[] remove(final long[] a, final long valueToRemove) { if (isEmpty(a)) { return EMPTY_LONG_ARRAY; } final int index = indexOf(a, valueToRemove, 0); return index == INDEX_NOT_FOUND ? a.clone() : deleteByIndex(a, index); } /** * Returns a new array with elements copied from the specified array except the first occurrence of the specified value. *
* The original array remains unchanged. * * @param a The array from which the value should be removed. * @param valueToRemove The value to be removed from the array. * @return A new array with the first occurrence of the specified value removed. An empty array is returned if the specified array is {@code null} or empty. */ public static float[] remove(final float[] a, final float valueToRemove) { if (isEmpty(a)) { return EMPTY_FLOAT_ARRAY; } final int index = indexOf(a, valueToRemove, 0); return index == INDEX_NOT_FOUND ? a.clone() : deleteByIndex(a, index); } /** * Returns a new array with elements copied from the specified array except the first occurrence of the specified value. *
* The original array remains unchanged. * * @param a The array from which the value should be removed. * @param valueToRemove The value to be removed from the array. * @return A new array with the first occurrence of the specified value removed. An empty array is returned if the specified array is {@code null} or empty. */ public static double[] remove(final double[] a, final double valueToRemove) { if (isEmpty(a)) { return EMPTY_DOUBLE_ARRAY; } final int index = indexOf(a, valueToRemove, 0); return index == INDEX_NOT_FOUND ? a.clone() : deleteByIndex(a, index); } /** * Returns a new array with elements copied from the specified array except the first occurrence of the specified value. *
* The original array remains unchanged. * * @param a The array from which the value should be removed. * @param valueToRemove The value to be removed from the array. * @return A new array with the first occurrence of the specified value removed. An empty array is returned if the specified array is {@code null} or empty. */ public static String[] remove(final String[] a, final String valueToRemove) { if (isEmpty(a)) { return EMPTY_STRING_ARRAY; } final int index = indexOf(a, valueToRemove, 0); return index == INDEX_NOT_FOUND ? a.clone() : deleteByIndex(a, index); } /** * Returns a new array with elements copied from the specified array except the first occurrence of the specified value. *
* The original array remains unchanged. * * @param a The array from which the value should be removed. * @param valueToRemove The value to be removed from the array. * @return A new array with the first occurrence of the specified value removed. The input array itself is returned if the specified array is {@code null} or empty. */ @MayReturnNull public static T[] remove(final T[] a, final T valueToRemove) throws IllegalArgumentException { if (isEmpty(a)) { return a; } final int index = indexOf(a, valueToRemove, 0); return index == INDEX_NOT_FOUND ? a.clone() : deleteByIndex(a, index); } /** * Removes the first occurrence of the specified value from the given collection. * * @param c The collection from which the value should be removed. * @param valueToRemove The value to be removed from the collection. * @return {@code true} if the collection changed as a result of this call, {@code false} otherwise. */ public static boolean remove(final Collection c, final T valueToRemove) { if (isEmpty(c)) { return false; } return c.remove(valueToRemove); } /** * Returns a new array with elements copied from the specified array except all occurrences of the specified values. *
* The original array remains unchanged. * * @param a The array from which the values should be removed. * @param valuesToRemove The values to be removed from the array. * @return A new array with all occurrences of the specified values removed. An empty array is returned if the specified array is {@code null} or empty. * @see N#difference(int[], int[]) */ @SafeVarargs public static boolean[] removeAll(final boolean[] a, final boolean... valuesToRemove) { if (isEmpty(a)) { return EMPTY_BOOLEAN_ARRAY; } else if (isEmpty(valuesToRemove)) { return a.clone(); } else if (valuesToRemove.length == 1) { return removeAllOccurrences(a, valuesToRemove[0]); } final BooleanList list = BooleanList.of(a.clone()); list.removeAll(BooleanList.of(valuesToRemove)); return list.trimToSize().array(); } /** * Returns a new array with elements copied from the specified array except all occurrences of the specified values. *
* The original array remains unchanged. * * @param a The array from which the values should be removed. * @param valuesToRemove The values to be removed from the array. * @return A new array with all occurrences of the specified values removed. An empty array is returned if the specified array is {@code null} or empty. * @see N#difference(int[], int[]) */ @SafeVarargs public static char[] removeAll(final char[] a, final char... valuesToRemove) { if (isEmpty(a)) { return EMPTY_CHAR_ARRAY; } else if (isEmpty(valuesToRemove)) { return a.clone(); } else if (valuesToRemove.length == 1) { return removeAllOccurrences(a, valuesToRemove[0]); } final CharList list = CharList.of(a.clone()); list.removeAll(CharList.of(valuesToRemove)); return list.trimToSize().array(); } /** * Returns a new array with elements copied from the specified array except all occurrences of the specified values. *
* The original array remains unchanged. * * @param a The array from which the values should be removed. * @param valuesToRemove The values to be removed from the array. * @return A new array with all occurrences of the specified values removed. An empty array is returned if the specified array is {@code null} or empty. * @see N#difference(int[], int[]) */ @SafeVarargs public static byte[] removeAll(final byte[] a, final byte... valuesToRemove) { if (isEmpty(a)) { return EMPTY_BYTE_ARRAY; } else if (isEmpty(valuesToRemove)) { return a.clone(); } else if (valuesToRemove.length == 1) { return removeAllOccurrences(a, valuesToRemove[0]); } final ByteList list = ByteList.of(a.clone()); list.removeAll(ByteList.of(valuesToRemove)); return list.trimToSize().array(); } /** * Returns a new array with elements copied from the specified array except all occurrences of the specified values. *
* The original array remains unchanged. * * @param a The array from which the values should be removed. * @param valuesToRemove The values to be removed from the array. * @return A new array with all occurrences of the specified values removed. An empty array is returned if the specified array is {@code null} or empty. * @see N#difference(int[], int[]) */ @SafeVarargs public static short[] removeAll(final short[] a, final short... valuesToRemove) { if (isEmpty(a)) { return EMPTY_SHORT_ARRAY; } else if (isEmpty(valuesToRemove)) { return a.clone(); } else if (valuesToRemove.length == 1) { return removeAllOccurrences(a, valuesToRemove[0]); } final ShortList list = ShortList.of(a.clone()); list.removeAll(ShortList.of(valuesToRemove)); return list.trimToSize().array(); } /** * Returns a new array with elements copied from the specified array except all occurrences of the specified values. *
* The original array remains unchanged. * * @param a The array from which the values should be removed. * @param valuesToRemove The values to be removed from the array. * @return A new array with all occurrences of the specified values removed. An empty array is returned if the specified array is {@code null} or empty. * @see N#difference(int[], int[]) */ @SafeVarargs public static int[] removeAll(final int[] a, final int... valuesToRemove) { if (isEmpty(a)) { return EMPTY_INT_ARRAY; } else if (isEmpty(valuesToRemove)) { return a.clone(); } else if (valuesToRemove.length == 1) { return removeAllOccurrences(a, valuesToRemove[0]); } final IntList list = IntList.of(a.clone()); list.removeAll(IntList.of(valuesToRemove)); return list.trimToSize().array(); } /** * Returns a new array with elements copied from the specified array except all occurrences of the specified values. *
* The original array remains unchanged. * * @param a The array from which the values should be removed. * @param valuesToRemove The values to be removed from the array. * @return A new array with all occurrences of the specified values removed. An empty array is returned if the specified array is {@code null} or empty. * @see N#difference(int[], int[]) */ @SafeVarargs public static long[] removeAll(final long[] a, final long... valuesToRemove) { if (isEmpty(a)) { return EMPTY_LONG_ARRAY; } else if (isEmpty(valuesToRemove)) { return a.clone(); } else if (valuesToRemove.length == 1) { return removeAllOccurrences(a, valuesToRemove[0]); } final LongList list = LongList.of(a.clone()); list.removeAll(LongList.of(valuesToRemove)); return list.trimToSize().array(); } /** * Returns a new array with elements copied from the specified array except all occurrences of the specified values. *
* The original array remains unchanged. * * @param a The array from which the values should be removed. * @param valuesToRemove The values to be removed from the array. * @return A new array with all occurrences of the specified values removed. An empty array is returned if the specified array is {@code null} or empty. * @see N#difference(int[], int[]) */ @SafeVarargs public static float[] removeAll(final float[] a, final float... valuesToRemove) { if (isEmpty(a)) { return EMPTY_FLOAT_ARRAY; } else if (isEmpty(valuesToRemove)) { return a.clone(); } else if (valuesToRemove.length == 1) { return removeAllOccurrences(a, valuesToRemove[0]); } final FloatList list = FloatList.of(a.clone()); list.removeAll(FloatList.of(valuesToRemove)); return list.trimToSize().array(); } /** * Returns a new array with elements copied from the specified array except all occurrences of the specified values. *
* The original array remains unchanged. * * @param a The array from which the values should be removed. * @param valuesToRemove The values to be removed from the array. * @return A new array with all occurrences of the specified values removed. An empty array is returned if the specified array is {@code null} or empty. * @see N#difference(int[], int[]) */ @SafeVarargs public static double[] removeAll(final double[] a, final double... valuesToRemove) { if (isEmpty(a)) { return EMPTY_DOUBLE_ARRAY; } else if (isEmpty(valuesToRemove)) { return a.clone(); } else if (valuesToRemove.length == 1) { return removeAllOccurrences(a, valuesToRemove[0]); } final DoubleList list = DoubleList.of(a.clone()); list.removeAll(DoubleList.of(valuesToRemove)); return list.trimToSize().array(); } /** * Returns a new array with elements copied from the specified array except all occurrences of the specified values. *
* The original array remains unchanged. * * @param a The array from which the values should be removed. * @param valuesToRemove The values to be removed from the array. * @return A new array with all occurrences of the specified values removed. An empty array is returned if the specified array is {@code null} or empty. * @see N#difference(int[], int[]) */ @SafeVarargs public static String[] removeAll(final String[] a, final String... valuesToRemove) { if (isEmpty(a)) { return EMPTY_STRING_ARRAY; } else if (isEmpty(valuesToRemove)) { return a.clone(); } else if (valuesToRemove.length == 1) { return removeAllOccurrences(a, valuesToRemove[0]); } final Set set = asSet(valuesToRemove); final List result = new ArrayList<>(); for (final String e : a) { if (!set.contains(e)) { result.add(e); } } return result.toArray(new String[0]); } /** * Returns a new array with elements copied from the specified array except all occurrences of the specified values. *
* The original array remains unchanged. * * @param a The array from which the values should be removed. * @param valuesToRemove The values to be removed from the array. * @return A new array with the first occurrence of the specified value removed. The input array itself is returned if the specified array is {@code null} or empty. * @see N#difference(int[], int[]) */ @MayReturnNull @SafeVarargs public static T[] removeAll(final T[] a, final T... valuesToRemove) { if (isEmpty(a)) { return a; } else if (isEmpty(valuesToRemove)) { return a.clone(); } else if (valuesToRemove.length == 1) { return removeAllOccurrences(a, valuesToRemove[0]); } final Set set = asSet(valuesToRemove); final List result = new ArrayList<>(); for (final T e : a) { if (!set.contains(e)) { result.add(e); } } return result.toArray((T[]) newArray(a.getClass().getComponentType(), result.size())); } /** * Removes all occurrences of the specified values from the given collection. * * @param The type of elements in the collection. * @param c The collection from which the values should be removed. * @param valuesToRemove The values to be removed from the collection. * @return {@code true} if the collection changed as a result of this call, {@code false} otherwise. */ @SafeVarargs public static boolean removeAll(final Collection c, final T... valuesToRemove) { if (isEmpty(c) || isEmpty(valuesToRemove)) { return false; } else { return removeAll(c, asSet(valuesToRemove)); } } /** * Removes all occurrences of the specified values from the given collection. * * @param The type of elements in the collection. * @param c The collection from which the values should be removed. * @param valuesToRemove The collection of values to be removed from the collection. * @return {@code true} if the collection changed as a result of this call, {@code false} otherwise. */ public static boolean removeAll(final Collection c, final Iterable valuesToRemove) { if (isEmpty(c) || valuesToRemove == null) { return false; } if (c instanceof HashSet && !(valuesToRemove instanceof Set)) { boolean wasModified = false; for (final Object e : valuesToRemove) { //noinspection SuspiciousMethodCalls wasModified |= c.remove(e); if (c.size() == 0) { break; } } return wasModified; } else { if (valuesToRemove instanceof final Collection coll) { // NOSONAR //noinspection SuspiciousMethodCalls return c.removeAll(coll); } else { return removeAll(c, valuesToRemove.iterator()); } } } /** * Removes all occurrences of the specified values from the given collection. * * @param The type of elements in the collection. * @param c The collection from which the elements should be removed. * @param valuesToRemove The iterator of values to be removed from the collection. * @return {@code true} if the collection changed as a result of this call, {@code false} otherwise. */ public static boolean removeAll(final Collection c, final Iterator valuesToRemove) { if (isEmpty(c) || valuesToRemove == null) { return false; } if (c instanceof final Set set) { final int originalSize = set.size(); while (valuesToRemove.hasNext()) { //noinspection SuspiciousMethodCalls set.remove(valuesToRemove.next()); } return set.size() != originalSize; } else { return removeAll(c, toSet(valuesToRemove)); } } /** * Returns a new array with elements copied from the specified array except all occurrence of the specified value. *
* The original array remains unchanged. * * @param a The array from which the value should be removed. * @param valueToRemove The value to be removed from the array. * @return a new array with all occurrences of the specified value removed. An empty array is returned if the specified array is {@code null} or empty. */ public static boolean[] removeAllOccurrences(final boolean[] a, final boolean valueToRemove) { if (isEmpty(a)) { return EMPTY_BOOLEAN_ARRAY; } final boolean[] copy = a.clone(); int idx = 0; for (final boolean element : a) { if (element == valueToRemove) { continue; } copy[idx++] = element; } return idx == copy.length ? copy : copyOfRange(copy, 0, idx); } /** * Returns a new array with elements copied from the specified array except all occurrence of the specified value. *
* The original array remains unchanged. * * @param a The array from which the value should be removed. * @param valueToRemove The value to be removed from the array. * @return a new array with all occurrences of the specified value removed. An empty array is returned if the specified array is {@code null} or empty. */ public static char[] removeAllOccurrences(final char[] a, final char valueToRemove) { if (isEmpty(a)) { return EMPTY_CHAR_ARRAY; } final char[] copy = a.clone(); int idx = 0; for (final char element : a) { if (element == valueToRemove) { continue; } copy[idx++] = element; } return idx == copy.length ? copy : copyOfRange(copy, 0, idx); } /** * Returns a new array with elements copied from the specified array except all occurrence of the specified value. *
* The original array remains unchanged. * * @param a The array from which the value should be removed. * @param valueToRemove The value to be removed from the array. * @return a new array with all occurrences of the specified value removed. An empty array is returned if the specified array is {@code null} or empty. */ public static byte[] removeAllOccurrences(final byte[] a, final byte valueToRemove) { if (isEmpty(a)) { return EMPTY_BYTE_ARRAY; } final byte[] copy = a.clone(); int idx = 0; for (final byte element : a) { if (element == valueToRemove) { continue; } copy[idx++] = element; } return idx == copy.length ? copy : copyOfRange(copy, 0, idx); } /** * Returns a new array with elements copied from the specified array except all occurrence of the specified value. *
* The original array remains unchanged. * * @param a The array from which the value should be removed. * @param valueToRemove The value to be removed from the array. * @return a new array with all occurrences of the specified value removed. An empty array is returned if the specified array is {@code null} or empty. */ public static short[] removeAllOccurrences(final short[] a, final short valueToRemove) { if (isEmpty(a)) { return EMPTY_SHORT_ARRAY; } final short[] copy = a.clone(); int idx = 0; for (final short element : a) { if (element == valueToRemove) { continue; } copy[idx++] = element; } return idx == copy.length ? copy : copyOfRange(copy, 0, idx); } /** * Returns a new array with elements copied from the specified array except all occurrence of the specified value. *
* The original array remains unchanged. * * @param a The array from which the value should be removed. * @param valueToRemove The value to be removed from the array. * @return a new array with all occurrences of the specified value removed. An empty array is returned if the specified array is {@code null} or empty. */ public static int[] removeAllOccurrences(final int[] a, final int valueToRemove) { if (isEmpty(a)) { return EMPTY_INT_ARRAY; } final int[] copy = a.clone(); int idx = 0; for (final int element : a) { if (element == valueToRemove) { continue; } copy[idx++] = element; } return idx == copy.length ? copy : copyOfRange(copy, 0, idx); } /** * Returns a new array with elements copied from the specified array except all occurrence of the specified value. *
* The original array remains unchanged. * * @param a The array from which the value should be removed. * @param valueToRemove The value to be removed from the array. * @return a new array with all occurrences of the specified value removed. An empty array is returned if the specified array is {@code null} or empty. */ public static long[] removeAllOccurrences(final long[] a, final long valueToRemove) { if (isEmpty(a)) { return EMPTY_LONG_ARRAY; } final long[] copy = a.clone(); int idx = 0; for (final long element : a) { if (element == valueToRemove) { continue; } copy[idx++] = element; } return idx == copy.length ? copy : copyOfRange(copy, 0, idx); } /** * Returns a new array with elements copied from the specified array except all occurrence of the specified value. *
* The original array remains unchanged. * * @param a The array from which the value should be removed. * @param valueToRemove The value to be removed from the array. * @return a new array with all occurrences of the specified value removed. An empty array is returned if the specified array is {@code null} or empty. */ public static float[] removeAllOccurrences(final float[] a, final float valueToRemove) { if (isEmpty(a)) { return EMPTY_FLOAT_ARRAY; } final float[] copy = a.clone(); int idx = 0; for (final float element : a) { if (equals(element, valueToRemove)) { continue; } copy[idx++] = element; } return idx == copy.length ? copy : copyOfRange(copy, 0, idx); } /** * Returns a new array with elements copied from the specified array except all occurrence of the specified value. *
* The original array remains unchanged. * * @param a The array from which the value should be removed. * @param valueToRemove The value to be removed from the array. * @return a new array with all occurrences of the specified value removed. An empty array is returned if the specified array is {@code null} or empty. */ public static double[] removeAllOccurrences(final double[] a, final double valueToRemove) { if (isEmpty(a)) { return EMPTY_DOUBLE_ARRAY; } final double[] copy = a.clone(); int idx = 0; for (final double element : a) { if (equals(element, valueToRemove)) { continue; } copy[idx++] = element; } return idx == copy.length ? copy : copyOfRange(copy, 0, idx); } /** * Returns a new array with elements copied from the specified array except all occurrence of the specified value. *
* The original array remains unchanged. * * @param a The array from which the value should be removed. * @param valueToRemove The value to be removed from the array. * @return a new array with all occurrences of the specified value removed. An empty array is returned if the specified array is {@code null} or empty. */ public static String[] removeAllOccurrences(final String[] a, final String valueToRemove) { if (isEmpty(a)) { return EMPTY_STRING_ARRAY; } final String[] copy = a.clone(); int idx = 0; for (final String element : a) { if (equals(element, valueToRemove)) { continue; } copy[idx++] = element; } return idx == copy.length ? copy : copyOfRange(copy, 0, idx); } /** * Returns a new array with elements copied from the specified array except all occurrence of the specified value. *
* The original array remains unchanged. * * @param a The array from which the value should be removed. * @param valueToRemove The value to be removed from the array. * @return a new array with all occurrences of the specified value removed. The input array itself is returned if the specified array is {@code null} or empty. */ public static T[] removeAllOccurrences(final T[] a, final T valueToRemove) { if (isEmpty(a)) { return a; } final T[] copy = a.clone(); int idx = 0; for (final T element : a) { if (equals(element, valueToRemove)) { continue; } copy[idx++] = element; } return idx == copy.length ? copy : copyOfRange(copy, 0, idx); } /** * Removes all occurrences of the specified value from the given collection. * * @param The type of elements in the collection. * @param c The collection from which the value should be removed. * @param valueToRemove The value to be removed from the collection. * @return {@code true} if the collection changed as a result of this call, {@code false} otherwise. */ public static boolean removeAllOccurrences(final Collection c, final T valueToRemove) { if (isEmpty(c)) { return false; } return removeAll(c, asSet(valueToRemove)); } /** * Returns a new array with elements from the input array but without any duplicates. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @return a new array with all duplicates removed. An empty array is returned if the specified array is {@code null} or empty. * @deprecated Use {@link #distinct(boolean[])} instead. */ @Deprecated public static boolean[] removeDuplicates(final boolean[] a) { if (isEmpty(a)) { return EMPTY_BOOLEAN_ARRAY; } return removeDuplicates(a, 0, a.length); } /** * Returns a new array with distinct elements within the specified range. *
* The original array remains unchanged. * * @param a The boolean array from which duplicates should be removed. * @param fromIndex The initial index of the range to be considered for duplicate removal. * @param toIndex The final index of the range to be considered for duplicate removal. * @return a new array with duplicate elements from the given array within the specified range * @throws IndexOutOfBoundsException if the range is out of the array bounds. * @deprecated Use {@link #distinct(boolean[], int, int)} instead. */ @Deprecated static boolean[] removeDuplicates(final boolean[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_BOOLEAN_ARRAY; } else if (toIndex - fromIndex <= 1) { return copyOfRange(a, fromIndex, toIndex); } final Boolean[] b = new Boolean[2]; for (int i = fromIndex; i < toIndex; i++) { if (b[0] == null) { b[0] = a[i]; } else if (b[0] != a[i]) { b[1] = a[i]; break; } } return b[1] == null ? new boolean[] { b[0] } : new boolean[] { b[0], b[1] }; } /** * Returns a new array with elements from the input array but without any duplicates. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @return a new array with all duplicates removed. An empty array is returned if the specified array is {@code null} or empty. * @deprecated Use {@link #distinct(char[])} instead. */ @Deprecated public static char[] removeDuplicates(final char[] a) { if (isEmpty(a)) { return EMPTY_CHAR_ARRAY; } return removeDuplicates(a, isSorted(a)); } /** * Returns a new array with elements from the input array but without any duplicates. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @param isSorted A boolean flag indicating whether the input array is sorted. If {@code true}, the algorithm will be faster * @return a new array with all duplicates removed. An empty array is returned if the specified array is {@code null} or empty. */ public static char[] removeDuplicates(final char[] a, final boolean isSorted) { if (isEmpty(a)) { return EMPTY_CHAR_ARRAY; } return removeDuplicates(a, 0, a.length, isSorted); } /** * Returns a new array with distinct elements within the specified range. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @param fromIndex The initial index of the range to be considered for duplicate removal. * @param toIndex The final index of the range to be considered for duplicate removal. * @param isSorted A boolean flag indicating whether the input array within the specified range is sorted. If {@code true}, the algorithm will be faster. * @return A new array with distinct elements within the specified range. * @throws IndexOutOfBoundsException if the range is out of the array bounds. */ public static char[] removeDuplicates(final char[] a, final int fromIndex, final int toIndex, final boolean isSorted) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_CHAR_ARRAY; } else if (toIndex - fromIndex <= 1) { return copyOfRange(a, fromIndex, toIndex); } if (isSorted) { final char[] b = (fromIndex == 0 && toIndex == a.length) ? a.clone() : copyOfRange(a, fromIndex, toIndex); int idx = 1; for (int i = 1, len = b.length; i < len; i++) { if (b[i] == b[i - 1]) { continue; } b[idx++] = b[i]; } return idx == b.length ? b : copyOfRange(b, 0, idx); } else { final Set set = newLinkedHashSet(a.length); for (int i = fromIndex; i < toIndex; i++) { set.add(a[i]); } if (set.size() == toIndex - fromIndex) { return (fromIndex == 0 && toIndex == a.length) ? a.clone() : copyOfRange(a, fromIndex, toIndex); } else { final char[] result = new char[set.size()]; int i = 0; for (final char e : set) { result[i++] = e; } return result; } } } /** * Returns a new array with elements from the input array but without any duplicates. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @return a new array with all duplicates removed. An empty array is returned if the specified array is {@code null} or empty. * @deprecated Use {@link #distinct(byte[])} instead. */ @Deprecated public static byte[] removeDuplicates(final byte[] a) { if (isEmpty(a)) { return EMPTY_BYTE_ARRAY; } return removeDuplicates(a, isSorted(a)); } /** * Returns a new array with elements from the input array but without any duplicates. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @param isSorted A boolean flag indicating whether the input array is sorted. If {@code true}, the algorithm will be faster * @return a new array with all duplicates removed. An empty array is returned if the specified array is {@code null} or empty. */ public static byte[] removeDuplicates(final byte[] a, final boolean isSorted) { if (isEmpty(a)) { return EMPTY_BYTE_ARRAY; } return removeDuplicates(a, 0, a.length, isSorted); } /** * Returns a new array with distinct elements within the specified range. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @param fromIndex The initial index of the range to be considered for duplicate removal. * @param toIndex The final index of the range to be considered for duplicate removal. * @param isSorted A boolean flag indicating whether the input array within the specified range is sorted. If {@code true}, the algorithm will be faster. * @return A new array with distinct elements within the specified range. * @throws IndexOutOfBoundsException if the range is out of the array bounds. */ public static byte[] removeDuplicates(final byte[] a, final int fromIndex, final int toIndex, final boolean isSorted) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_BYTE_ARRAY; } else if (toIndex - fromIndex <= 1) { return copyOfRange(a, fromIndex, toIndex); } if (isSorted) { final byte[] b = (fromIndex == 0 && toIndex == a.length) ? a.clone() : copyOfRange(a, fromIndex, toIndex); int idx = 1; for (int i = 1, len = b.length; i < len; i++) { if (b[i] == b[i - 1]) { continue; } b[idx++] = b[i]; } return idx == b.length ? b : copyOfRange(b, 0, idx); } else { final Set set = newLinkedHashSet(a.length); for (int i = fromIndex; i < toIndex; i++) { set.add(a[i]); } if (set.size() == toIndex - fromIndex) { return (fromIndex == 0 && toIndex == a.length) ? a.clone() : copyOfRange(a, fromIndex, toIndex); } else { final byte[] result = new byte[set.size()]; int i = 0; for (final byte e : set) { result[i++] = e; } return result; } } } /** * Returns a new array with elements from the input array but without any duplicates. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @return a new array with all duplicates removed. An empty array is returned if the specified array is {@code null} or empty. * @deprecated Use {@link #distinct(short[])} instead. */ @Deprecated public static short[] removeDuplicates(final short[] a) { if (isEmpty(a)) { return EMPTY_SHORT_ARRAY; } return removeDuplicates(a, isSorted(a)); } /** * Returns a new array with elements from the input array but without any duplicates. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @param isSorted A boolean flag indicating whether the input array is sorted. If {@code true}, the algorithm will be faster * @return a new array with all duplicates removed. An empty array is returned if the specified array is {@code null} or empty. */ public static short[] removeDuplicates(final short[] a, final boolean isSorted) { if (isEmpty(a)) { return EMPTY_SHORT_ARRAY; } return removeDuplicates(a, 0, a.length, isSorted); } /** * Returns a new array with distinct elements within the specified range. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @param fromIndex The initial index of the range to be considered for duplicate removal. * @param toIndex The final index of the range to be considered for duplicate removal. * @param isSorted A boolean flag indicating whether the input array within the specified range is sorted. If {@code true}, the algorithm will be faster. * @return A new array with distinct elements within the specified range. * @throws IndexOutOfBoundsException if the range is out of the array bounds. */ public static short[] removeDuplicates(final short[] a, final int fromIndex, final int toIndex, final boolean isSorted) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_SHORT_ARRAY; } else if (toIndex - fromIndex <= 1) { return copyOfRange(a, fromIndex, toIndex); } if (isSorted) { final short[] b = (fromIndex == 0 && toIndex == a.length) ? a.clone() : copyOfRange(a, fromIndex, toIndex); int idx = 1; for (int i = 1, len = b.length; i < len; i++) { if (b[i] == b[i - 1]) { continue; } b[idx++] = b[i]; } return idx == b.length ? b : copyOfRange(b, 0, idx); } else { final Set set = newLinkedHashSet(a.length); for (int i = fromIndex; i < toIndex; i++) { set.add(a[i]); } if (set.size() == toIndex - fromIndex) { return (fromIndex == 0 && toIndex == a.length) ? a.clone() : copyOfRange(a, fromIndex, toIndex); } else { final short[] result = new short[set.size()]; int i = 0; for (final short e : set) { result[i++] = e; } return result; } } } /** * Returns a new array with elements from the input array but without any duplicates. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @return a new array with all duplicates removed. An empty array is returned if the specified array is {@code null} or empty. * @deprecated Use {@link #distinct(int[])} instead. */ @Deprecated public static int[] removeDuplicates(final int[] a) { if (isEmpty(a)) { return EMPTY_INT_ARRAY; } return removeDuplicates(a, isSorted(a)); } /** * Returns a new array with elements from the input array but without any duplicates. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @param isSorted A boolean flag indicating whether the input array is sorted. If {@code true}, the algorithm will be faster * @return a new array with all duplicates removed. An empty array is returned if the specified array is {@code null} or empty. */ public static int[] removeDuplicates(final int[] a, final boolean isSorted) { if (isEmpty(a)) { return EMPTY_INT_ARRAY; } return removeDuplicates(a, 0, a.length, isSorted); } /** * Returns a new array with distinct elements within the specified range. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @param fromIndex The initial index of the range to be considered for duplicate removal. * @param toIndex The final index of the range to be considered for duplicate removal. * @param isSorted A boolean flag indicating whether the input array within the specified range is sorted. If {@code true}, the algorithm will be faster. * @return A new array with distinct elements within the specified range. * @throws IndexOutOfBoundsException if the range is out of the array bounds. */ public static int[] removeDuplicates(final int[] a, final int fromIndex, final int toIndex, final boolean isSorted) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_INT_ARRAY; } else if (toIndex - fromIndex <= 1) { return copyOfRange(a, fromIndex, toIndex); } if (isSorted) { final int[] b = (fromIndex == 0 && toIndex == a.length) ? a.clone() : copyOfRange(a, fromIndex, toIndex); int idx = 1; for (int i = 1, len = b.length; i < len; i++) { if (b[i] == b[i - 1]) { continue; } b[idx++] = b[i]; } return idx == b.length ? b : copyOfRange(b, 0, idx); } else { final Set set = newLinkedHashSet(a.length); for (int i = fromIndex; i < toIndex; i++) { set.add(a[i]); } if (set.size() == toIndex - fromIndex) { return (fromIndex == 0 && toIndex == a.length) ? a.clone() : copyOfRange(a, fromIndex, toIndex); } else { final int[] result = new int[set.size()]; int i = 0; for (final int e : set) { result[i++] = e; } return result; } } } /** * Returns a new array with elements from the input array but without any duplicates. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @return a new array with all duplicates removed. An empty array is returned if the specified array is {@code null} or empty. * @deprecated Use {@link #distinct(long[])} instead. */ @Deprecated public static long[] removeDuplicates(final long[] a) { if (isEmpty(a)) { return EMPTY_LONG_ARRAY; } return removeDuplicates(a, isSorted(a)); } /** * Returns a new array with elements from the input array but without any duplicates. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @param isSorted A boolean flag indicating whether the input array is sorted. If {@code true}, the algorithm will be faster * @return a new array with all duplicates removed. An empty array is returned if the specified array is {@code null} or empty. */ public static long[] removeDuplicates(final long[] a, final boolean isSorted) { if (isEmpty(a)) { return EMPTY_LONG_ARRAY; } return removeDuplicates(a, 0, a.length, isSorted); } /** * Returns a new array with distinct elements within the specified range. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @param fromIndex The initial index of the range to be considered for duplicate removal. * @param toIndex The final index of the range to be considered for duplicate removal. * @param isSorted A boolean flag indicating whether the input array within the specified range is sorted. If {@code true}, the algorithm will be faster. * @return A new array with distinct elements within the specified range. * @throws IndexOutOfBoundsException if the range is out of the array bounds. */ public static long[] removeDuplicates(final long[] a, final int fromIndex, final int toIndex, final boolean isSorted) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_LONG_ARRAY; } else if (toIndex - fromIndex <= 1) { return copyOfRange(a, fromIndex, toIndex); } if (isSorted) { final long[] b = (fromIndex == 0 && toIndex == a.length) ? a.clone() : copyOfRange(a, fromIndex, toIndex); int idx = 1; for (int i = 1, len = b.length; i < len; i++) { if (b[i] == b[i - 1]) { continue; } b[idx++] = b[i]; } return idx == b.length ? b : copyOfRange(b, 0, idx); } else { final Set set = newLinkedHashSet(a.length); for (int i = fromIndex; i < toIndex; i++) { set.add(a[i]); } if (set.size() == toIndex - fromIndex) { return (fromIndex == 0 && toIndex == a.length) ? a.clone() : copyOfRange(a, fromIndex, toIndex); } else { final long[] result = new long[set.size()]; int i = 0; for (final long e : set) { result[i++] = e; } return result; } } } /** * Returns a new array with elements from the input array but without any duplicates. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @return a new array with all duplicates removed. An empty array is returned if the specified array is {@code null} or empty. * @deprecated Use {@link #distinct(float[])} instead. */ @Deprecated public static float[] removeDuplicates(final float[] a) { if (isEmpty(a)) { return EMPTY_FLOAT_ARRAY; } return removeDuplicates(a, isSorted(a)); } /** * Returns a new array with elements from the input array but without any duplicates. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @param isSorted A boolean flag indicating whether the input array is sorted. If {@code true}, the algorithm will be faster * @return a new array with all duplicates removed. An empty array is returned if the specified array is {@code null} or empty. */ public static float[] removeDuplicates(final float[] a, final boolean isSorted) { if (isEmpty(a)) { return EMPTY_FLOAT_ARRAY; } return removeDuplicates(a, 0, a.length, isSorted); } /** * Returns a new array with distinct elements within the specified range. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @param fromIndex The initial index of the range to be considered for duplicate removal. * @param toIndex The final index of the range to be considered for duplicate removal. * @param isSorted A boolean flag indicating whether the input array within the specified range is sorted. If {@code true}, the algorithm will be faster. * @return A new array with distinct elements within the specified range. * @throws IndexOutOfBoundsException if the range is out of the array bounds. */ public static float[] removeDuplicates(final float[] a, final int fromIndex, final int toIndex, final boolean isSorted) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_FLOAT_ARRAY; } else if (toIndex - fromIndex <= 1) { return copyOfRange(a, fromIndex, toIndex); } if (isSorted) { final float[] b = (fromIndex == 0 && toIndex == a.length) ? a.clone() : copyOfRange(a, fromIndex, toIndex); int idx = 1; for (int i = 1, len = b.length; i < len; i++) { if (equals(b[i], b[i - 1])) { continue; } b[idx++] = b[i]; } return idx == b.length ? b : copyOfRange(b, 0, idx); } else { final Set set = newLinkedHashSet(a.length); for (int i = fromIndex; i < toIndex; i++) { set.add(a[i]); } if (set.size() == toIndex - fromIndex) { return (fromIndex == 0 && toIndex == a.length) ? a.clone() : copyOfRange(a, fromIndex, toIndex); } else { final float[] result = new float[set.size()]; int i = 0; for (final float e : set) { result[i++] = e; } return result; } } } /** * Returns a new array with elements from the input array but without any duplicates. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @return a new array with all duplicates removed. An empty array is returned if the specified array is {@code null} or empty. * @deprecated Use {@link #distinct(double[])} instead. */ @Deprecated public static double[] removeDuplicates(final double[] a) { if (isEmpty(a)) { return EMPTY_DOUBLE_ARRAY; } return removeDuplicates(a, isSorted(a)); } /** * Returns a new array with elements from the input array but without any duplicates. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @param isSorted A boolean flag indicating whether the input array is sorted. If {@code true}, the algorithm will be faster * @return a new array with all duplicates removed. An empty array is returned if the specified array is {@code null} or empty. */ public static double[] removeDuplicates(final double[] a, final boolean isSorted) { if (isEmpty(a)) { return EMPTY_DOUBLE_ARRAY; } return removeDuplicates(a, 0, a.length, isSorted); } /** * Returns a new array with distinct elements within the specified range. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @param fromIndex The initial index of the range to be considered for duplicate removal. * @param toIndex The final index of the range to be considered for duplicate removal. * @param isSorted A boolean flag indicating whether the input array within the specified range is sorted. If {@code true}, the algorithm will be faster. * @return A new array with distinct elements within the specified range. * @throws IndexOutOfBoundsException if the range is out of the array bounds. */ public static double[] removeDuplicates(final double[] a, final int fromIndex, final int toIndex, final boolean isSorted) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_DOUBLE_ARRAY; } else if (toIndex - fromIndex <= 1) { return copyOfRange(a, fromIndex, toIndex); } if (isSorted) { final double[] b = (fromIndex == 0 && toIndex == a.length) ? a.clone() : copyOfRange(a, fromIndex, toIndex); int idx = 1; for (int i = 1, len = b.length; i < len; i++) { if (equals(b[i], b[i - 1])) { continue; } b[idx++] = b[i]; } return idx == b.length ? b : copyOfRange(b, 0, idx); } else { final Set set = newLinkedHashSet(a.length); for (int i = fromIndex; i < toIndex; i++) { set.add(a[i]); } if (set.size() == toIndex - fromIndex) { return (fromIndex == 0 && toIndex == a.length) ? a.clone() : copyOfRange(a, fromIndex, toIndex); } else { final double[] result = new double[set.size()]; int i = 0; for (final double e : set) { result[i++] = e; } return result; } } } /** * Returns a new array with elements from the input array but without any duplicates. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @return a new array with all duplicates removed. An empty array is returned if the specified array is {@code null} or empty. * @see #distinct(Object[]) */ public static String[] removeDuplicates(final String[] a) { if (isEmpty(a)) { return EMPTY_STRING_ARRAY; } return removeDuplicates(a, isSorted(a)); } /** * Returns a new array with elements from the input array but without any duplicates. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @param isSorted A boolean flag indicating whether the input array is sorted. If {@code true}, the algorithm will be faster * @return a new array with all duplicates removed. An empty array is returned if the specified array is {@code null} or empty. */ public static String[] removeDuplicates(final String[] a, final boolean isSorted) { if (isEmpty(a)) { return EMPTY_STRING_ARRAY; } return removeDuplicates(a, 0, a.length, isSorted); } /** * Returns a new array with distinct elements within the specified range. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @param fromIndex The initial index of the range to be considered for duplicate removal. * @param toIndex The final index of the range to be considered for duplicate removal. * @param isSorted A boolean flag indicating whether the input array within the specified range is sorted. If {@code true}, the algorithm will be faster. * @return A new array with distinct elements within the specified range. * @throws IndexOutOfBoundsException if the range is out of the array bounds. */ public static String[] removeDuplicates(final String[] a, final int fromIndex, final int toIndex, final boolean isSorted) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_STRING_ARRAY; } else if (toIndex - fromIndex <= 1) { return copyOfRange(a, fromIndex, toIndex); } if (isSorted) { final String[] b = (fromIndex == 0 && toIndex == a.length) ? a.clone() : copyOfRange(a, fromIndex, toIndex); int idx = 1; for (int i = 1, len = b.length; i < len; i++) { if (equals(b[i], b[i - 1])) { continue; } b[idx++] = b[i]; } return idx == b.length ? b : copyOfRange(b, 0, idx); } else { final Set set = newLinkedHashSet(a.length); //noinspection ManualArrayToCollectionCopy for (int i = fromIndex; i < toIndex; i++) { set.add(a[i]); //NOSONAR } if (set.size() == toIndex - fromIndex) { return (fromIndex == 0 && toIndex == a.length) ? a.clone() : copyOfRange(a, fromIndex, toIndex); } else { final String[] result = new String[set.size()]; int i = 0; for (final String e : set) { result[i++] = e; } return result; } } } /** * Returns a new array with elements from the input array but without any duplicates. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @return a new array with all duplicates removed. The input array itself is returned if the specified array is {@code null} or empty. * @see #distinct(Object[]) */ public static T[] removeDuplicates(final T[] a) { if (isEmpty(a)) { return a; } return removeDuplicates(a, false); } /** * Returns a new array with elements from the input array but without any duplicates. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @param isSorted A boolean flag indicating whether the input array is sorted. If {@code true}, the algorithm will be faster * @return a new array with all duplicates removed. The input array itself is returned if the specified array is {@code null} or empty. */ public static T[] removeDuplicates(final T[] a, final boolean isSorted) { if (isEmpty(a)) { return a; } return removeDuplicates(a, 0, a.length, isSorted); } /** * Returns a new array with distinct elements within the specified range. *
* The original array remains unchanged. * * @param a The array from which duplicates should be removed. * @param fromIndex The initial index of the range to be considered for duplicate removal. * @param toIndex The final index of the range to be considered for duplicate removal. * @param isSorted A boolean flag indicating whether the input array within the specified range is sorted. If {@code true}, the algorithm will be faster. * @return A new array with distinct elements within the specified range. * @throws IndexOutOfBoundsException if the range is out of the array bounds. */ public static T[] removeDuplicates(final T[] a, final int fromIndex, final int toIndex, final boolean isSorted) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return a; } else if (toIndex - fromIndex <= 1) { return copyOfRange(a, fromIndex, toIndex); } if (isSorted) { final T[] b = (fromIndex == 0 && toIndex == a.length) ? a.clone() : copyOfRange(a, fromIndex, toIndex); int idx = 1; for (int i = 1, len = b.length; i < len; i++) { if (equals(b[i], b[i - 1])) { continue; } b[idx++] = b[i]; } return idx == b.length ? b : copyOfRange(b, 0, idx); } else { final List list = distinct(a, fromIndex, toIndex); return list.toArray((T[]) newArray(a.getClass().getComponentType(), list.size())); } } /** * Removes duplicate elements from the given collection. * * @param c The collection from which duplicates should be removed. * @return {@code true} if the collection changed as a result of this call, {@code false} otherwise. * @see #distinct(Iterable) * @see #distinctBy(Iterable, Function) */ public static boolean removeDuplicates(final Collection c) { return removeDuplicates(c, false); } /** * Removes duplicate elements from the given collection. * * @param c The collection from which duplicates should be removed. * @param isSorted A boolean flag indicating whether the input array is sorted. If {@code true}, the algorithm will be faster * @return {@code true} if the collection changed as a result of this call, {@code false} otherwise. * @see #distinct(Iterable) * @see #distinctBy(Iterable, Function) */ @SuppressWarnings("rawtypes") public static boolean removeDuplicates(final Collection c, final boolean isSorted) { if (isEmpty(c) || c.size() == 1 || c instanceof Set) { return false; } else if (c.size() == 2) { final Iterator iter = c.iterator(); final Object first = iter.next(); if (equals(first, iter.next())) { iter.remove(); return true; } else { return false; } } if (isSorted) { boolean hasDuplicates = false; final Iterator it = c.iterator(); Object pre = it.next(); Object next = null; while (it.hasNext()) { next = it.next(); if (equals(next, pre)) { it.remove(); hasDuplicates = true; } else { pre = next; } } return hasDuplicates; } else { final List list = distinct(c); final boolean hasDuplicates = list.size() != c.size(); if (hasDuplicates) { c.clear(); c.addAll((List) list); } return hasDuplicates; } } /** * Returns a new array with the specified range of elements removed *
* The original array remains unchanged. * * @param a the input array from which a range of elements are to be deleted * @param fromIndex the initial index of the range to be deleted, inclusive * @param toIndex the final index of the range to be deleted, exclusive * @return a new array with the specified range of elements removed. An empty array is returned if the specified array is {@code null} or empty. * @throws IndexOutOfBoundsException if the range is out of the array bounds */ public static boolean[] deleteRange(final boolean[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (fromIndex == toIndex) { return a == null ? EMPTY_BOOLEAN_ARRAY : a.clone(); } final int len = len(a); final boolean[] b = new boolean[len - (toIndex - fromIndex)]; if (fromIndex > 0) { copy(a, 0, b, 0, fromIndex); } if (toIndex < len) { copy(a, toIndex, b, fromIndex, len - toIndex); } return b; } /** * Returns a new array with the specified range of elements removed *
* The original array remains unchanged. * * @param a the input array from which a range of elements are to be deleted * @param fromIndex the initial index of the range to be deleted, inclusive * @param toIndex the final index of the range to be deleted, exclusive * @return a new array with the specified range of elements removed. An empty array is returned if the specified array is {@code null} or empty. * @throws IndexOutOfBoundsException if the range is out of the array bounds */ public static char[] deleteRange(final char[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (fromIndex == toIndex) { return a == null ? EMPTY_CHAR_ARRAY : a.clone(); } final int len = len(a); final char[] b = new char[len - (toIndex - fromIndex)]; if (fromIndex > 0) { copy(a, 0, b, 0, fromIndex); } if (toIndex < len) { copy(a, toIndex, b, fromIndex, len - toIndex); } return b; } /** * Returns a new array with the specified range of elements removed *
* The original array remains unchanged. * * @param a the input array from which a range of elements are to be deleted * @param fromIndex the initial index of the range to be deleted, inclusive * @param toIndex the final index of the range to be deleted, exclusive * @return a new array with the specified range of elements removed. An empty array is returned if the specified array is {@code null} or empty. * @throws IndexOutOfBoundsException if the range is out of the array bounds */ public static byte[] deleteRange(final byte[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (fromIndex == toIndex) { return a == null ? EMPTY_BYTE_ARRAY : a.clone(); } final int len = len(a); final byte[] b = new byte[len - (toIndex - fromIndex)]; if (fromIndex > 0) { copy(a, 0, b, 0, fromIndex); } if (toIndex < len) { copy(a, toIndex, b, fromIndex, len - toIndex); } return b; } /** * Returns a new array with the specified range of elements removed *
* The original array remains unchanged. * * @param a the input array from which a range of elements are to be deleted * @param fromIndex the initial index of the range to be deleted, inclusive * @param toIndex the final index of the range to be deleted, exclusive * @return a new array with the specified range of elements removed. An empty array is returned if the specified array is {@code null} or empty. * @throws IndexOutOfBoundsException if the range is out of the array bounds */ public static short[] deleteRange(final short[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (fromIndex == toIndex) { return a == null ? EMPTY_SHORT_ARRAY : a.clone(); } final int len = len(a); final short[] b = new short[len - (toIndex - fromIndex)]; if (fromIndex > 0) { copy(a, 0, b, 0, fromIndex); } if (toIndex < len) { copy(a, toIndex, b, fromIndex, len - toIndex); } return b; } /** * Returns a new array with the specified range of elements removed *
* The original array remains unchanged. * * @param a the input array from which a range of elements are to be deleted * @param fromIndex the initial index of the range to be deleted, inclusive * @param toIndex the final index of the range to be deleted, exclusive * @return a new array with the specified range of elements removed. An empty array is returned if the specified array is {@code null} or empty. * @throws IndexOutOfBoundsException if the range is out of the array bounds */ public static int[] deleteRange(final int[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (fromIndex == toIndex) { return a == null ? EMPTY_INT_ARRAY : a.clone(); } final int len = len(a); final int[] b = new int[len - (toIndex - fromIndex)]; if (fromIndex > 0) { copy(a, 0, b, 0, fromIndex); } if (toIndex < len) { copy(a, toIndex, b, fromIndex, len - toIndex); } return b; } /** * Returns a new array with the specified range of elements removed *
* The original array remains unchanged. * * @param a the input array from which a range of elements are to be deleted * @param fromIndex the initial index of the range to be deleted, inclusive * @param toIndex the final index of the range to be deleted, exclusive * @return a new array with the specified range of elements removed. An empty array is returned if the specified array is {@code null} or empty. * @throws IndexOutOfBoundsException if the range is out of the array bounds */ public static long[] deleteRange(final long[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (fromIndex == toIndex) { return a == null ? EMPTY_LONG_ARRAY : a.clone(); } final int len = len(a); final long[] b = new long[len - (toIndex - fromIndex)]; if (fromIndex > 0) { copy(a, 0, b, 0, fromIndex); } if (toIndex < len) { copy(a, toIndex, b, fromIndex, len - toIndex); } return b; } /** * Returns a new array with the specified range of elements removed *
* The original array remains unchanged. * * @param a the input array from which a range of elements are to be deleted * @param fromIndex the initial index of the range to be deleted, inclusive * @param toIndex the final index of the range to be deleted, exclusive * @return a new array with the specified range of elements removed. An empty array is returned if the specified array is {@code null} or empty. * @throws IndexOutOfBoundsException if the range is out of the array bounds */ public static float[] deleteRange(final float[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (fromIndex == toIndex) { return a == null ? EMPTY_FLOAT_ARRAY : a.clone(); } final int len = len(a); final float[] b = new float[len - (toIndex - fromIndex)]; if (fromIndex > 0) { copy(a, 0, b, 0, fromIndex); } if (toIndex < len) { copy(a, toIndex, b, fromIndex, len - toIndex); } return b; } /** * Returns a new array with the specified range of elements removed *
* The original array remains unchanged. * * @param a the input array from which a range of elements are to be deleted * @param fromIndex the initial index of the range to be deleted, inclusive * @param toIndex the final index of the range to be deleted, exclusive * @return a new array with the specified range of elements removed. An empty array is returned if the specified array is {@code null} or empty. * @throws IndexOutOfBoundsException if the range is out of the array bounds */ public static double[] deleteRange(final double[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (fromIndex == toIndex) { return a == null ? EMPTY_DOUBLE_ARRAY : a.clone(); } final int len = len(a); final double[] b = new double[len - (toIndex - fromIndex)]; if (fromIndex > 0) { copy(a, 0, b, 0, fromIndex); } if (toIndex < len) { copy(a, toIndex, b, fromIndex, len - toIndex); } return b; } /** * Returns a new array with the specified range of elements removed *
* The original array remains unchanged. * * @param a the input array from which a range of elements are to be deleted * @param fromIndex the initial index of the range to be deleted, inclusive * @param toIndex the final index of the range to be deleted, exclusive * @return a new array with the specified range of elements removed. An empty array is returned if the specified array is {@code null} or empty. * @throws IndexOutOfBoundsException if the range is out of the array bounds */ public static String[] deleteRange(final String[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException, IllegalArgumentException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (fromIndex == toIndex) { return a == null ? EMPTY_STRING_ARRAY : a.clone(); } final int len = len(a); final String[] b = new String[len - (toIndex - fromIndex)]; if (fromIndex > 0) { copy(a, 0, b, 0, fromIndex); } if (toIndex < len) { copy(a, toIndex, b, fromIndex, len - toIndex); } return b; } /** * Returns a new array with the specified range of elements removed *
* The original array remains unchanged. * * @param a the input array from which a range of elements are to be deleted * @param fromIndex the initial index of the range to be deleted, inclusive * @param toIndex the final index of the range to be deleted, exclusive * @return a new array with the specified range of elements removed * @throws IndexOutOfBoundsException if the range is out of the array bounds * @see #skipRange(Object[], int, int) */ public static T[] deleteRange(@NotNull final T[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException, IndexOutOfBoundsException { // checkArgNotNull(a, cs.a); return skipRange(a, fromIndex, toIndex); } /** * Deletes a range of elements from the given list. * * @param the type of elements in the list * @param c the input list from which a range of elements are to be deleted * @param fromIndex the initial index of the range to be deleted, inclusive * @param toIndex the final index of the range to be deleted, exclusive * @return {@code true} if the list is updated; {@code false} otherwise * @throws IndexOutOfBoundsException if the range is out of the list bounds */ public static boolean deleteRange(final List c, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); if (fromIndex == toIndex) { return false; } final int size = size(c); if (c instanceof LinkedList || toIndex - fromIndex <= 3) { c.subList(fromIndex, toIndex).clear(); } else { final List tmp = new ArrayList<>(size - (toIndex - fromIndex)); if (fromIndex > 0) { tmp.addAll(c.subList(0, fromIndex)); } if (toIndex < size) { tmp.addAll(c.subList(toIndex, size)); } c.clear(); c.addAll(tmp); } return true; } /** * Returns a new String with the specified range of chars removed *
* The original String remains unchanged. * * @param str the input string from which a range of characters are to be deleted * @param fromIndex the initial index of the range to be deleted, inclusive * @param toIndex the final index of the range to be deleted, exclusive * @return a new string with the specified range of characters deleted. An empty String is returned if the specified String is {@code null} or empty. * @throws IndexOutOfBoundsException if the range is out of the string bounds * @see Strings#deleteRange(String, int, int) */ public static String deleteRange(final String str, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { return Strings.deleteRange(str, fromIndex, toIndex); } /** * Returns a new array with the specified range replaced with the replacement array. *
* The original array remains unchanged. * * @param a the original array * @param fromIndex the initial index of the range to be replaced, inclusive * @param toIndex the final index of the range to be replaced, exclusive * @param replacement the array to replace the specified range in the original array * @return a new array with the specified range replaced by the replacement array * @throws IndexOutOfBoundsException if the range is out of the array bounds */ public static boolean[] replaceRange(final boolean[] a, final int fromIndex, final int toIndex, final boolean[] replacement) throws IndexOutOfBoundsException { final int len = len(a); checkFromToIndex(fromIndex, toIndex, len); if (isEmpty(a)) { return isEmpty(replacement) ? EMPTY_BOOLEAN_ARRAY : replacement.clone(); } else if (isEmpty(replacement)) { return deleteRange(a, fromIndex, toIndex); } final boolean[] result = new boolean[len - (toIndex - fromIndex) + replacement.length]; if (fromIndex > 0) { copy(a, 0, result, 0, fromIndex); } copy(replacement, 0, result, fromIndex, replacement.length); if (toIndex < len) { copy(a, toIndex, result, fromIndex + replacement.length, len - toIndex); } return result; } /** * Returns a new array with the specified range replaced with the replacement array. *
* The original array remains unchanged. * * @param a the original array * @param fromIndex the initial index of the range to be replaced, inclusive * @param toIndex the final index of the range to be replaced, exclusive * @param replacement the array to replace the specified range in the original array * @return a new array with the specified range replaced by the replacement array * @throws IndexOutOfBoundsException if the range is out of the array bounds */ public static char[] replaceRange(final char[] a, final int fromIndex, final int toIndex, final char[] replacement) throws IndexOutOfBoundsException { final int len = len(a); checkFromToIndex(fromIndex, toIndex, len); if (isEmpty(a)) { return isEmpty(replacement) ? EMPTY_CHAR_ARRAY : replacement.clone(); } else if (isEmpty(replacement)) { return deleteRange(a, fromIndex, toIndex); } final char[] result = new char[len - (toIndex - fromIndex) + replacement.length]; if (fromIndex > 0) { copy(a, 0, result, 0, fromIndex); } copy(replacement, 0, result, fromIndex, replacement.length); if (toIndex < len) { copy(a, toIndex, result, fromIndex + replacement.length, len - toIndex); } return result; } /** * Returns a new array with the specified range replaced with the replacement array. *
* The original array remains unchanged. * * @param a the original array * @param fromIndex the initial index of the range to be replaced, inclusive * @param toIndex the final index of the range to be replaced, exclusive * @param replacement the array to replace the specified range in the original array * @return a new array with the specified range replaced by the replacement array * @throws IndexOutOfBoundsException if the range is out of the array bounds */ public static byte[] replaceRange(final byte[] a, final int fromIndex, final int toIndex, final byte[] replacement) throws IndexOutOfBoundsException { final int len = len(a); checkFromToIndex(fromIndex, toIndex, len); if (isEmpty(a)) { return isEmpty(replacement) ? EMPTY_BYTE_ARRAY : replacement.clone(); } else if (isEmpty(replacement)) { return deleteRange(a, fromIndex, toIndex); } final byte[] result = new byte[len - (toIndex - fromIndex) + replacement.length]; if (fromIndex > 0) { copy(a, 0, result, 0, fromIndex); } copy(replacement, 0, result, fromIndex, replacement.length); if (toIndex < len) { copy(a, toIndex, result, fromIndex + replacement.length, len - toIndex); } return result; } /** * Returns a new array with the specified range replaced with the replacement array. *
* The original array remains unchanged. * * @param a the original array * @param fromIndex the initial index of the range to be replaced, inclusive * @param toIndex the final index of the range to be replaced, exclusive * @param replacement the array to replace the specified range in the original array * @return a new array with the specified range replaced by the replacement array * @throws IndexOutOfBoundsException if the range is out of the array bounds */ public static short[] replaceRange(final short[] a, final int fromIndex, final int toIndex, final short[] replacement) throws IndexOutOfBoundsException { final int len = len(a); checkFromToIndex(fromIndex, toIndex, len); if (isEmpty(a)) { return isEmpty(replacement) ? EMPTY_SHORT_ARRAY : replacement.clone(); } else if (isEmpty(replacement)) { return deleteRange(a, fromIndex, toIndex); } final short[] result = new short[len - (toIndex - fromIndex) + replacement.length]; if (fromIndex > 0) { copy(a, 0, result, 0, fromIndex); } copy(replacement, 0, result, fromIndex, replacement.length); if (toIndex < len) { copy(a, toIndex, result, fromIndex + replacement.length, len - toIndex); } return result; } /** * Returns a new array with the specified range replaced with the replacement array. *
* The original array remains unchanged. * * @param a the original array * @param fromIndex the initial index of the range to be replaced, inclusive * @param toIndex the final index of the range to be replaced, exclusive * @param replacement the array to replace the specified range in the original array * @return a new array with the specified range replaced by the replacement array * @throws IndexOutOfBoundsException if the range is out of the array bounds */ public static int[] replaceRange(final int[] a, final int fromIndex, final int toIndex, final int[] replacement) throws IndexOutOfBoundsException { final int len = len(a); checkFromToIndex(fromIndex, toIndex, len); if (isEmpty(a)) { return isEmpty(replacement) ? EMPTY_INT_ARRAY : replacement.clone(); } else if (isEmpty(replacement)) { return deleteRange(a, fromIndex, toIndex); } final int[] result = new int[len - (toIndex - fromIndex) + replacement.length]; if (fromIndex > 0) { copy(a, 0, result, 0, fromIndex); } copy(replacement, 0, result, fromIndex, replacement.length); if (toIndex < len) { copy(a, toIndex, result, fromIndex + replacement.length, len - toIndex); } return result; } /** * Returns a new array with the specified range replaced with the replacement array. *
* The original array remains unchanged. * * @param a the original array * @param fromIndex the initial index of the range to be replaced, inclusive * @param toIndex the final index of the range to be replaced, exclusive * @param replacement the array to replace the specified range in the original array * @return a new array with the specified range replaced by the replacement array * @throws IndexOutOfBoundsException if the range is out of the array bounds */ public static long[] replaceRange(final long[] a, final int fromIndex, final int toIndex, final long[] replacement) throws IndexOutOfBoundsException { final int len = len(a); checkFromToIndex(fromIndex, toIndex, len); if (isEmpty(a)) { return isEmpty(replacement) ? EMPTY_LONG_ARRAY : replacement.clone(); } else if (isEmpty(replacement)) { return deleteRange(a, fromIndex, toIndex); } final long[] result = new long[len - (toIndex - fromIndex) + replacement.length]; if (fromIndex > 0) { copy(a, 0, result, 0, fromIndex); } copy(replacement, 0, result, fromIndex, replacement.length); if (toIndex < len) { copy(a, toIndex, result, fromIndex + replacement.length, len - toIndex); } return result; } /** * Returns a new array with the specified range replaced with the replacement array. *
* The original array remains unchanged. * * @param a the original array * @param fromIndex the initial index of the range to be replaced, inclusive * @param toIndex the final index of the range to be replaced, exclusive * @param replacement the array to replace the specified range in the original array * @return a new array with the specified range replaced by the replacement array * @throws IndexOutOfBoundsException if the range is out of the array bounds */ public static float[] replaceRange(final float[] a, final int fromIndex, final int toIndex, final float[] replacement) throws IndexOutOfBoundsException { final int len = len(a); checkFromToIndex(fromIndex, toIndex, len); if (isEmpty(a)) { return isEmpty(replacement) ? EMPTY_FLOAT_ARRAY : replacement.clone(); } else if (isEmpty(replacement)) { return deleteRange(a, fromIndex, toIndex); } final float[] result = new float[len - (toIndex - fromIndex) + replacement.length]; if (fromIndex > 0) { copy(a, 0, result, 0, fromIndex); } copy(replacement, 0, result, fromIndex, replacement.length); if (toIndex < len) { copy(a, toIndex, result, fromIndex + replacement.length, len - toIndex); } return result; } /** * Returns a new array with the specified range replaced with the replacement array. *
* The original array remains unchanged. * * @param a the original array * @param fromIndex the initial index of the range to be replaced, inclusive * @param toIndex the final index of the range to be replaced, exclusive * @param replacement the array to replace the specified range in the original array * @return a new array with the specified range replaced by the replacement array * @throws IndexOutOfBoundsException if the range is out of the array bounds */ public static double[] replaceRange(final double[] a, final int fromIndex, final int toIndex, final double[] replacement) throws IndexOutOfBoundsException { final int len = len(a); checkFromToIndex(fromIndex, toIndex, len); if (isEmpty(a)) { return isEmpty(replacement) ? EMPTY_DOUBLE_ARRAY : replacement.clone(); } else if (isEmpty(replacement)) { return deleteRange(a, fromIndex, toIndex); } final double[] result = new double[len - (toIndex - fromIndex) + replacement.length]; if (fromIndex > 0) { copy(a, 0, result, 0, fromIndex); } copy(replacement, 0, result, fromIndex, replacement.length); if (toIndex < len) { copy(a, toIndex, result, fromIndex + replacement.length, len - toIndex); } return result; } /** * Returns a new array with the specified range replaced with the replacement array. *
* The original array remains unchanged. * * @param a the original array * @param fromIndex the initial index of the range to be replaced, inclusive * @param toIndex the final index of the range to be replaced, exclusive * @param replacement the array to replace the specified range in the original array * @return a new array with the specified range replaced by the replacement array * @throws IndexOutOfBoundsException if the range is out of the array bounds */ public static String[] replaceRange(final String[] a, final int fromIndex, final int toIndex, final String[] replacement) throws IndexOutOfBoundsException { final int len = len(a); checkFromToIndex(fromIndex, toIndex, len); if (isEmpty(a)) { return isEmpty(replacement) ? EMPTY_STRING_ARRAY : replacement.clone(); } else if (isEmpty(replacement)) { return deleteRange(a, fromIndex, toIndex); } final String[] result = new String[len - (toIndex - fromIndex) + replacement.length]; if (fromIndex > 0) { copy(a, 0, result, 0, fromIndex); } copy(replacement, 0, result, fromIndex, replacement.length); if (toIndex < len) { copy(a, toIndex, result, fromIndex + replacement.length, len - toIndex); } return result; } /** * Returns a new array with the specified range replaced with the replacement array. *
* The original array remains unchanged. * * @param a the original array * @param fromIndex the initial index of the range to be replaced, inclusive * @param toIndex the final index of the range to be replaced, exclusive * @param replacement the array to replace the specified range in the original array * @return a new array with the specified range replaced by the replacement array * @throws IndexOutOfBoundsException if the range is out of the array bounds */ public static T[] replaceRange(@NotNull final T[] a, final int fromIndex, final int toIndex, final T[] replacement) throws IllegalArgumentException, IndexOutOfBoundsException { // checkArgNotNull(a, cs.a); final int len = len(a); checkFromToIndex(fromIndex, toIndex, len); if (isEmpty(a)) { return isEmpty(replacement) ? a : replacement.clone(); } else if (isEmpty(replacement)) { return deleteRange(a, fromIndex, toIndex); } final T[] result = newArray(a.getClass().getComponentType(), len - (toIndex - fromIndex) + replacement.length); if (fromIndex > 0) { copy(a, 0, result, 0, fromIndex); } copy(replacement, 0, result, fromIndex, replacement.length); if (toIndex < len) { copy(a, toIndex, result, fromIndex + replacement.length, len - toIndex); } return result; } /** * Replaces a range of elements in the given list with the elements from the replacement collection. * * @param the type of elements in the list and replacement collection * @param c the original list to be modified * @param fromIndex the initial index of the range to be replaced, inclusive * @param toIndex the final index of the range to be replaced, exclusive * @param replacement the collection to replace the specified range in the original list * @return a boolean indicating whether the list was modified * @throws IndexOutOfBoundsException if the range is out of the list bounds */ public static boolean replaceRange(@NotNull final List c, final int fromIndex, final int toIndex, final Collection replacement) throws IllegalArgumentException { // checkArgNotNull(c, cs.c); final int size = size(c); checkFromToIndex(fromIndex, toIndex, size); if (isEmpty(replacement)) { if (fromIndex == toIndex) { return false; } return deleteRange(c, fromIndex, toIndex); } final List endList = toIndex < size ? new ArrayList<>(c.subList(toIndex, size)) : null; if (fromIndex < size) { deleteRange(c, fromIndex, size); } c.addAll(replacement); if (notEmpty(endList)) { c.addAll(endList); } return true; } /** * Returns a new String with the specified range replaced with the replacement String. *
* The original String remains unchanged. * * @param str the original string * @param fromIndex the initial index of the range to be replaced, inclusive * @param toIndex the final index of the range to be replaced, exclusive * @param replacement the string to replace the specified range in the original string * @return a new string with the specified range replaced by the replacement string * @throws IndexOutOfBoundsException if the range is out of the string bounds * @see Strings#replaceRange(String, int, int, String) */ public static String replaceRange(final String str, final int fromIndex, final int toIndex, final String replacement) throws IndexOutOfBoundsException { return Strings.replaceRange(str, fromIndex, toIndex, replacement); } /** * Moves a range of elements in the given array to a new position within the array. *
* No elements are deleted in the process, the original array maintains its size. * * @param a the original array to be modified * @param fromIndex the initial index of the range to be moved, inclusive * @param toIndex the final index of the range to be moved, exclusive * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] * @throws IndexOutOfBoundsException if the range is out of the array bounds or newPositionStartIndex is invalid */ public static void moveRange(final boolean[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) throws IndexOutOfBoundsException { final int len = len(a); checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len); if (fromIndex == toIndex || fromIndex == newPositionStartIndex) { return; } final boolean[] rangeTmp = copyOfRange(a, fromIndex, toIndex); // move ahead if (newPositionStartIndex < fromIndex) { copy(a, newPositionStartIndex, a, toIndex - (fromIndex - newPositionStartIndex), fromIndex - newPositionStartIndex); } else { copy(a, toIndex, a, fromIndex, newPositionStartIndex - fromIndex); } copy(rangeTmp, 0, a, newPositionStartIndex, rangeTmp.length); } /** * Moves a range of elements in the given array to a new position within the array. *
* No elements are deleted in the process, the original array maintains its size. * * @param a the original array to be modified * @param fromIndex the initial index of the range to be moved, inclusive * @param toIndex the final index of the range to be moved, exclusive * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] * @throws IndexOutOfBoundsException if the range is out of the array bounds or newPositionStartIndex is invalid */ public static void moveRange(final char[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) throws IndexOutOfBoundsException { final int len = len(a); checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len); if (fromIndex == toIndex || fromIndex == newPositionStartIndex) { return; } final char[] rangeTmp = copyOfRange(a, fromIndex, toIndex); // move ahead if (newPositionStartIndex < fromIndex) { copy(a, newPositionStartIndex, a, toIndex - (fromIndex - newPositionStartIndex), fromIndex - newPositionStartIndex); } else { copy(a, toIndex, a, fromIndex, newPositionStartIndex - fromIndex); } copy(rangeTmp, 0, a, newPositionStartIndex, rangeTmp.length); } /** * Moves a range of elements in the given array to a new position within the array. *
* No elements are deleted in the process, the original array maintains its size. * * @param a the original array to be modified * @param fromIndex the initial index of the range to be moved, inclusive * @param toIndex the final index of the range to be moved, exclusive * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] * @throws IndexOutOfBoundsException if the range is out of the array bounds or newPositionStartIndex is invalid */ public static void moveRange(final byte[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) throws IndexOutOfBoundsException { final int len = len(a); checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len); if (fromIndex == toIndex || fromIndex == newPositionStartIndex) { return; } final byte[] rangeTmp = copyOfRange(a, fromIndex, toIndex); // move ahead if (newPositionStartIndex < fromIndex) { copy(a, newPositionStartIndex, a, toIndex - (fromIndex - newPositionStartIndex), fromIndex - newPositionStartIndex); } else { copy(a, toIndex, a, fromIndex, newPositionStartIndex - fromIndex); } copy(rangeTmp, 0, a, newPositionStartIndex, rangeTmp.length); } /** * Moves a range of elements in the given array to a new position within the array. *
* No elements are deleted in the process, the original array maintains its size. * * @param a the original array to be modified * @param fromIndex the initial index of the range to be moved, inclusive * @param toIndex the final index of the range to be moved, exclusive * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] * @throws IndexOutOfBoundsException if the range is out of the array bounds or newPositionStartIndex is invalid */ public static void moveRange(final short[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) throws IndexOutOfBoundsException { final int len = len(a); checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len); if (fromIndex == toIndex || fromIndex == newPositionStartIndex) { return; } final short[] rangeTmp = copyOfRange(a, fromIndex, toIndex); // move ahead if (newPositionStartIndex < fromIndex) { copy(a, newPositionStartIndex, a, toIndex - (fromIndex - newPositionStartIndex), fromIndex - newPositionStartIndex); } else { copy(a, toIndex, a, fromIndex, newPositionStartIndex - fromIndex); } copy(rangeTmp, 0, a, newPositionStartIndex, rangeTmp.length); } /** * Moves a range of elements in the given array to a new position within the array. *
* No elements are deleted in the process, the original array maintains its size. * * @param a the original array to be modified * @param fromIndex the initial index of the range to be moved, inclusive * @param toIndex the final index of the range to be moved, exclusive * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] * @throws IndexOutOfBoundsException if the range is out of the array bounds or newPositionStartIndex is invalid */ public static void moveRange(final int[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) throws IndexOutOfBoundsException { final int len = len(a); checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len); if (fromIndex == toIndex || fromIndex == newPositionStartIndex) { return; } final int[] rangeTmp = copyOfRange(a, fromIndex, toIndex); // move ahead if (newPositionStartIndex < fromIndex) { copy(a, newPositionStartIndex, a, toIndex - (fromIndex - newPositionStartIndex), fromIndex - newPositionStartIndex); } else { copy(a, toIndex, a, fromIndex, newPositionStartIndex - fromIndex); } copy(rangeTmp, 0, a, newPositionStartIndex, rangeTmp.length); } /** * Moves a range of elements in the given array to a new position within the array. *
* No elements are deleted in the process, the original array maintains its size. * * @param a the original array to be modified * @param fromIndex the initial index of the range to be moved, inclusive * @param toIndex the final index of the range to be moved, exclusive * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] * @throws IndexOutOfBoundsException if the range is out of the array bounds or newPositionStartIndex is invalid */ public static void moveRange(final long[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) throws IndexOutOfBoundsException { final int len = len(a); checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len); if (fromIndex == toIndex || fromIndex == newPositionStartIndex) { return; } final long[] rangeTmp = copyOfRange(a, fromIndex, toIndex); // move ahead if (newPositionStartIndex < fromIndex) { copy(a, newPositionStartIndex, a, toIndex - (fromIndex - newPositionStartIndex), fromIndex - newPositionStartIndex); } else { copy(a, toIndex, a, fromIndex, newPositionStartIndex - fromIndex); } copy(rangeTmp, 0, a, newPositionStartIndex, rangeTmp.length); } /** * Moves a range of elements in the given array to a new position within the array. *
* No elements are deleted in the process, the original array maintains its size. * * @param a the original array to be modified * @param fromIndex the initial index of the range to be moved, inclusive * @param toIndex the final index of the range to be moved, exclusive * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] * @throws IndexOutOfBoundsException if the range is out of the array bounds or newPositionStartIndex is invalid */ public static void moveRange(final float[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) throws IndexOutOfBoundsException { final int len = len(a); checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len); if (fromIndex == toIndex || fromIndex == newPositionStartIndex) { return; } final float[] rangeTmp = copyOfRange(a, fromIndex, toIndex); // move ahead if (newPositionStartIndex < fromIndex) { copy(a, newPositionStartIndex, a, toIndex - (fromIndex - newPositionStartIndex), fromIndex - newPositionStartIndex); } else { copy(a, toIndex, a, fromIndex, newPositionStartIndex - fromIndex); } copy(rangeTmp, 0, a, newPositionStartIndex, rangeTmp.length); } /** * Moves a range of elements in the given array to a new position within the array. *
* No elements are deleted in the process, the original array maintains its size. * * @param a the original array to be modified * @param fromIndex the initial index of the range to be moved, inclusive * @param toIndex the final index of the range to be moved, exclusive * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] * @throws IndexOutOfBoundsException if the range is out of the array bounds or newPositionStartIndex is invalid */ public static void moveRange(final double[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) throws IndexOutOfBoundsException { final int len = len(a); checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len); if (fromIndex == toIndex || fromIndex == newPositionStartIndex) { return; } final double[] rangeTmp = copyOfRange(a, fromIndex, toIndex); // move ahead if (newPositionStartIndex < fromIndex) { copy(a, newPositionStartIndex, a, toIndex - (fromIndex - newPositionStartIndex), fromIndex - newPositionStartIndex); } else { copy(a, toIndex, a, fromIndex, newPositionStartIndex - fromIndex); } copy(rangeTmp, 0, a, newPositionStartIndex, rangeTmp.length); } /** * Moves a range of elements in the given array to a new position within the array. *
* No elements are deleted in the process, the original array maintains its size. * * @param a the original array to be modified * @param fromIndex the initial index of the range to be moved, inclusive * @param toIndex the final index of the range to be moved, exclusive * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] * @throws IndexOutOfBoundsException if the range is out of the array bounds or newPositionStartIndex is invalid */ public static void moveRange(final T[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) throws IndexOutOfBoundsException { final int len = len(a); checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len); if (fromIndex == toIndex || fromIndex == newPositionStartIndex) { return; } final T[] rangeTmp = copyOfRange(a, fromIndex, toIndex); // move ahead if (newPositionStartIndex < fromIndex) { copy(a, newPositionStartIndex, a, toIndex - (fromIndex - newPositionStartIndex), fromIndex - newPositionStartIndex); } else { copy(a, toIndex, a, fromIndex, newPositionStartIndex - fromIndex); } copy(rangeTmp, 0, a, newPositionStartIndex, rangeTmp.length); } /** * Moves a range of elements in the given list to a new position within the list. *
* No elements are deleted in the process, the original list maintains its size. * * @param the type of elements in the list * @param c the original list to be modified * @param fromIndex the initial index of the range to be moved, inclusive * @param toIndex the final index of the range to be moved, exclusive * @param newPositionStartIndex must in the range: [0, list.size() - (toIndex - fromIndex)] * @return {@code true} if the list was modified as a result of this operation * @throws IndexOutOfBoundsException if the range is out of the list bounds or newPositionStartIndex is invalid */ public static boolean moveRange(final List c, final int fromIndex, final int toIndex, final int newPositionStartIndex) throws IndexOutOfBoundsException { final int size = size(c); checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, size); if (fromIndex == toIndex || fromIndex == newPositionStartIndex) { return false; } final T[] tmp = (T[]) c.toArray(); moveRange(tmp, fromIndex, toIndex, newPositionStartIndex); c.clear(); c.addAll(Arrays.asList(tmp)); return true; } /** * Returns a new string with the specified range moved to the new position. *
* The original String remains unchanged. * * @param str the original string to be modified * @param fromIndex the initial index of the range to be moved, inclusive * @param toIndex the final index of the range to be moved, exclusive * @param newPositionStartIndex must in the range: [0, String.length - (toIndex - fromIndex)] * @return a new string with the specified range moved to the new position * @throws IndexOutOfBoundsException if the range is out of the string bounds or newPositionStartIndex is invalid * @see Strings#moveRange(String, int, int, int) */ public static String moveRange(final String str, final int fromIndex, final int toIndex, final int newPositionStartIndex) throws IndexOutOfBoundsException { return Strings.moveRange(str, fromIndex, toIndex, newPositionStartIndex); } static void checkIndexAndStartPositionForMoveRange(final int fromIndex, final int toIndex, final int newPositionStartIndex, final int len) { checkFromToIndex(fromIndex, toIndex, len); if (newPositionStartIndex < 0 || newPositionStartIndex > (len - (toIndex - fromIndex))) { throw new IndexOutOfBoundsException("newPositionStartIndex " + newPositionStartIndex + " is out-of-bounds: [0, " + (len - (toIndex - fromIndex)) + "=(array.length - (toIndex - fromIndex))]"); } } // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static boolean[] copyThenMoveRange(final boolean[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final boolean[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static char[] copyThenMoveRange(final char[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final char[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static byte[] copyThenMoveRange(final byte[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final byte[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static short[] copyThenMoveRange(final short[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final short[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static int[] copyThenMoveRange(final int[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final int[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static long[] copyThenMoveRange(final long[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final long[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static double[] copyThenMoveRange(final double[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final double[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static T[] copyThenMoveRange(final T[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final T[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static boolean[] copyThenMoveRange(final boolean[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final boolean[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static char[] copyThenMoveRange(final char[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final char[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static byte[] copyThenMoveRange(final byte[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final byte[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static short[] copyThenMoveRange(final short[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final short[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static int[] copyThenMoveRange(final int[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final int[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static long[] copyThenMoveRange(final long[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final long[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static double[] copyThenMoveRange(final double[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final double[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static T[] copyThenMoveRange(final T[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final T[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static boolean[] copyThenMoveRange(final boolean[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final boolean[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static char[] copyThenMoveRange(final char[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final char[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static byte[] copyThenMoveRange(final byte[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final byte[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static short[] copyThenMoveRange(final short[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final short[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static int[] copyThenMoveRange(final int[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final int[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static long[] copyThenMoveRange(final long[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final long[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static double[] copyThenMoveRange(final double[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final double[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } // // /** // * Returns a new array copy. // * // * @param a // * @param fromIndex // * @param toIndex // * @param newPositionStartIndex must in the range: [0, array.length - (toIndex - fromIndex)] // * @return a new array. // */ // public static T[] copyThenMoveRange(final T[] a, final int fromIndex, final int toIndex, final int newPositionStartIndex) { // checkIndexAndStartPositionForMoveRange(fromIndex, toIndex, newPositionStartIndex, len(a)); // NOSONAR // // final T[] copy = isEmpty(a) ? a : a.clone(); // // moveRange(copy, fromIndex, toIndex, newPositionStartIndex); // // return copy; // } /** * Returns a new array with the specified range skipped. *
* The original array remains unchanged. * * @param the type of elements in the input array * @param a the original array to be modified * @param startInclusive the initial index of the range to be skipped, inclusive * @param endExclusive the final index of the range to be skipped, exclusive * @return a new array with the specified range skipped * @throws IndexOutOfBoundsException if the range is out of the array bounds * @see #deleteRange(Object[], int, int) */ public static T[] skipRange(final T[] a, final int startInclusive, final int endExclusive) throws IndexOutOfBoundsException { final int len = len(a); checkFromToIndex(startInclusive, endExclusive, len); if (a == null) { return null; } else if (startInclusive == endExclusive) { return a.clone(); } final T[] ret = N.newArray(a.getClass().getComponentType(), len - (endExclusive - startInclusive)); if (startInclusive > 0) { N.copy(a, 0, ret, 0, startInclusive); } if (endExclusive < len) { N.copy(a, endExclusive, ret, startInclusive, len - endExclusive); } return ret; } /** * Returns a new list with the specified range skipped. *
* The original collection remains unchanged. * * @param the type of elements in the input collection * @param c the original collection to be modified * @param startInclusive the initial index of the range to be skipped, inclusive * @param endExclusive the final index of the range to be skipped, exclusive * @return a new list with the specified range skipped * @throws IndexOutOfBoundsException if the range is out of the collection bounds */ public static List skipRange(final Collection c, final int startInclusive, final int endExclusive) throws IndexOutOfBoundsException { return skipRange(c, startInclusive, endExclusive, IntFunctions.ofList()); } /** * Returns a new collection with the specified range skipped. *
* The original collection remains unchanged. * * @param the type of elements in the input collection * @param the type of the collection to be returned * @param c the original collection to be modified * @param startInclusive the initial index of the range to be skipped, inclusive * @param endExclusive the final index of the range to be skipped, exclusive * @param supplier a function that creates a new instance of the desired collection type * @return a new collection with the specified range skipped * @throws IndexOutOfBoundsException if the range is out of the collection bounds */ public static > C skipRange(final Collection c, final int startInclusive, final int endExclusive, final IntFunction supplier) throws IndexOutOfBoundsException { final int size = size(c); checkFromToIndex(startInclusive, endExclusive, size); final C result = supplier.apply(size - (endExclusive - startInclusive)); if (size == 0) { return result; } if (c instanceof List) { final List list = (List) c; if (startInclusive > 0) { result.addAll(list.subList(0, startInclusive)); } if (endExclusive < size) { result.addAll(list.subList(endExclusive, size)); } } else { final Iterator iter = c.iterator(); for (int i = 0; i < startInclusive; i++) { result.add(iter.next()); } if (endExclusive < size) { int idx = startInclusive; while (idx++ < endExclusive) { iter.next(); } while (iter.hasNext()) { result.add(iter.next()); } } } return result; } // Primitive/Object array converters // ---------------------------------------------------------------------- /** * Checks if the given array has duplicate elements. * * @param a the array to be checked for duplicates * @return {@code true} if the array has duplicates, {@code false} otherwise */ public static boolean hasDuplicates(final boolean[] a) { if (isEmpty(a)) { return false; } return hasDuplicates(a, 0, a.length); } /** * Checks if the given array has duplicate elements within the specified range. * * @param a the array to be checked for duplicates * @param fromIndex The start index (inclusive) of the range to be checked * @param toIndex the end index (exclusive) of the range to be checked * @return {@code true} if the array has duplicates within the specified range, {@code false} otherwise * @throws IndexOutOfBoundsException if the range is out of bounds for the given array */ static boolean hasDuplicates(final boolean[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || toIndex - fromIndex < 2) { return false; } else if (toIndex - fromIndex == 2) { return a[fromIndex] == a[fromIndex + 1]; } else { return true; } } /** * Checks if the given array has duplicate elements. * * @param a the array to be checked for duplicates * @return {@code true} if the array has duplicates, {@code false} otherwise */ public static boolean hasDuplicates(final char[] a) { return hasDuplicates(a, false); } /** * Checks if the given array has duplicate elements. * * @param a the array to be checked for duplicates * @param isSorted a boolean that indicates if the array is sorted. If {@code true}, the algorithm will be faster. * @return {@code true} if the array has duplicates, {@code false} otherwise */ public static boolean hasDuplicates(final char[] a, final boolean isSorted) { if (isEmpty(a)) { return false; } return hasDuplicates(a, 0, a.length, isSorted); } /** * Checks if the given array has duplicate elements within the specified range. * * @param a the array to be checked for duplicates * @param fromIndex The start index (inclusive) of the range to be checked * @param toIndex the end index (exclusive) of the range to be checked * @param isSorted a boolean that indicates if the array is sorted. If {@code true}, the algorithm will be faster. * @return {@code true} if the array has duplicates within the specified range, {@code false} otherwise * @throws IndexOutOfBoundsException if the range is out of bounds for the given array */ static boolean hasDuplicates(final char[] a, final int fromIndex, final int toIndex, final boolean isSorted) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || toIndex - fromIndex < 2) { return false; } else if (toIndex - fromIndex == 2) { return a[fromIndex] == a[fromIndex + 1]; } else if (toIndex - fromIndex == 3) { return a[fromIndex] == a[fromIndex + 1] || a[fromIndex] == a[fromIndex + 2] || a[fromIndex + 1] == a[fromIndex + 2]; } if (isSorted) { for (int i = fromIndex + 1; i < toIndex; i++) { if (a[i] == a[i - 1]) { return true; } } } else { final Set set = newHashSet(toIndex - fromIndex); for (int i = fromIndex; i < toIndex; i++) { if (!set.add(a[i])) { return true; } } } return false; } /** * Checks if the given array has duplicate elements. * * @param a the array to be checked for duplicates * @return {@code true} if the array has duplicates, {@code false} otherwise */ public static boolean hasDuplicates(final byte[] a) { return hasDuplicates(a, false); } /** * Checks if the given array has duplicate elements. * * @param a the array to be checked for duplicates * @param isSorted a boolean that indicates if the array is sorted. If {@code true}, the algorithm will be faster. * @return {@code true} if the array has duplicates, {@code false} otherwise */ public static boolean hasDuplicates(final byte[] a, final boolean isSorted) { if (isEmpty(a)) { return false; } return hasDuplicates(a, 0, a.length, isSorted); } /** * Checks if the given array has duplicate elements within the specified range. * * @param a the array to be checked for duplicates * @param fromIndex The start index (inclusive) of the range to be checked * @param toIndex the end index (exclusive) of the range to be checked * @param isSorted a boolean that indicates if the array is sorted. If {@code true}, the algorithm will be faster. * @return {@code true} if the array has duplicates within the specified range, {@code false} otherwise * @throws IndexOutOfBoundsException if the range is out of bounds for the given array */ static boolean hasDuplicates(final byte[] a, final int fromIndex, final int toIndex, final boolean isSorted) { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || toIndex - fromIndex < 2) { return false; } else if (toIndex - fromIndex == 2) { return a[fromIndex] == a[fromIndex + 1]; } else if (toIndex - fromIndex == 3) { return a[fromIndex] == a[fromIndex + 1] || a[fromIndex] == a[fromIndex + 2] || a[fromIndex + 1] == a[fromIndex + 2]; } if (isSorted) { for (int i = fromIndex + 1; i < toIndex; i++) { if (a[i] == a[i - 1]) { return true; } } } else { final Set set = newHashSet(toIndex - fromIndex); for (int i = fromIndex; i < toIndex; i++) { if (!set.add(a[i])) { return true; } } } return false; } /** * Checks if the given array has duplicate elements. * * @param a the array to be checked for duplicates * @return {@code true} if the array has duplicates, {@code false} otherwise */ public static boolean hasDuplicates(final short[] a) { return hasDuplicates(a, false); } /** * Checks if the given array has duplicate elements. * * @param a the array to be checked for duplicates * @param isSorted a boolean that indicates if the array is sorted. If {@code true}, the algorithm will be faster. * @return {@code true} if the array has duplicates, {@code false} otherwise */ public static boolean hasDuplicates(final short[] a, final boolean isSorted) { if (isEmpty(a)) { return false; } return hasDuplicates(a, 0, a.length, isSorted); } /** * Checks if the given array has duplicate elements within the specified range. * * @param a the array to be checked for duplicates * @param fromIndex The start index (inclusive) of the range to be checked * @param toIndex the end index (exclusive) of the range to be checked * @param isSorted a boolean that indicates if the array is sorted. If {@code true}, the algorithm will be faster. * @return {@code true} if the array has duplicates within the specified range, {@code false} otherwise * @throws IndexOutOfBoundsException if the range is out of bounds for the given array */ static boolean hasDuplicates(final short[] a, final int fromIndex, final int toIndex, final boolean isSorted) { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || toIndex - fromIndex < 2) { return false; } else if (toIndex - fromIndex == 2) { return a[fromIndex] == a[fromIndex + 1]; } else if (toIndex - fromIndex == 3) { return a[fromIndex] == a[fromIndex + 1] || a[fromIndex] == a[fromIndex + 2] || a[fromIndex + 1] == a[fromIndex + 2]; } if (isSorted) { for (int i = fromIndex + 1; i < toIndex; i++) { if (a[i] == a[i - 1]) { return true; } } } else { final Set set = newHashSet(toIndex - fromIndex); for (int i = fromIndex; i < toIndex; i++) { if (!set.add(a[i])) { return true; } } } return false; } /** * Checks if the given array has duplicate elements. * * @param a the array to be checked for duplicates * @return {@code true} if the array has duplicates, {@code false} otherwise */ public static boolean hasDuplicates(final int[] a) { return hasDuplicates(a, false); } /** * Checks if the given array has duplicate elements. * * @param a the array to be checked for duplicates * @param isSorted a boolean that indicates if the array is sorted. If {@code true}, the algorithm will be faster. * @return {@code true} if the array has duplicates, {@code false} otherwise */ public static boolean hasDuplicates(final int[] a, final boolean isSorted) { if (isEmpty(a)) { return false; } return hasDuplicates(a, 0, a.length, isSorted); } /** * Checks if the given array has duplicate elements within the specified range. * * @param a the array to be checked for duplicates * @param fromIndex The start index (inclusive) of the range to be checked * @param toIndex the end index (exclusive) of the range to be checked * @param isSorted a boolean that indicates if the array is sorted. If {@code true}, the algorithm will be faster. * @return {@code true} if the array has duplicates within the specified range, {@code false} otherwise * @throws IndexOutOfBoundsException if the range is out of bounds for the given array */ static boolean hasDuplicates(final int[] a, final int fromIndex, final int toIndex, final boolean isSorted) { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || toIndex - fromIndex < 2) { return false; } else if (toIndex - fromIndex == 2) { return a[fromIndex] == a[fromIndex + 1]; } else if (toIndex - fromIndex == 3) { return a[fromIndex] == a[fromIndex + 1] || a[fromIndex] == a[fromIndex + 2] || a[fromIndex + 1] == a[fromIndex + 2]; } if (isSorted) { for (int i = fromIndex + 1; i < toIndex; i++) { if (a[i] == a[i - 1]) { return true; } } } else { final Set set = newHashSet(toIndex - fromIndex); for (int i = fromIndex; i < toIndex; i++) { if (!set.add(a[i])) { return true; } } } return false; } /** * Checks if the given array has duplicate elements. * * @param a the array to be checked for duplicates * @return {@code true} if the array has duplicates, {@code false} otherwise */ public static boolean hasDuplicates(final long[] a) { return hasDuplicates(a, false); } /** * Checks if the given array has duplicate elements. * * @param a the array to be checked for duplicates * @param isSorted a boolean that indicates if the array is sorted. If {@code true}, the algorithm will be faster. * @return {@code true} if the array has duplicates, {@code false} otherwise */ public static boolean hasDuplicates(final long[] a, final boolean isSorted) { if (isEmpty(a)) { return false; } return hasDuplicates(a, 0, a.length, isSorted); } /** * Checks if the given array has duplicate elements within the specified range. * * @param a the array to be checked for duplicates * @param fromIndex The start index (inclusive) of the range to be checked * @param toIndex the end index (exclusive) of the range to be checked * @param isSorted a boolean that indicates if the array is sorted. If {@code true}, the algorithm will be faster. * @return {@code true} if the array has duplicates within the specified range, {@code false} otherwise * @throws IndexOutOfBoundsException if the range is out of bounds for the given array */ static boolean hasDuplicates(final long[] a, final int fromIndex, final int toIndex, final boolean isSorted) { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || toIndex - fromIndex < 2) { return false; } else if (toIndex - fromIndex == 2) { return a[fromIndex] == a[fromIndex + 1]; } else if (toIndex - fromIndex == 3) { return a[fromIndex] == a[fromIndex + 1] || a[fromIndex] == a[fromIndex + 2] || a[fromIndex + 1] == a[fromIndex + 2]; } if (isSorted) { for (int i = fromIndex + 1; i < toIndex; i++) { if (a[i] == a[i - 1]) { return true; } } } else { final Set set = newHashSet(toIndex - fromIndex); for (int i = fromIndex; i < toIndex; i++) { if (!set.add(a[i])) { return true; } } } return false; } /** * Checks if the given array has duplicate elements. * * @param a the array to be checked for duplicates * @return {@code true} if the array has duplicates, {@code false} otherwise */ public static boolean hasDuplicates(final float[] a) { return hasDuplicates(a, false); } /** * Checks if the given array has duplicate elements. * * @param a the array to be checked for duplicates * @param isSorted a boolean that indicates if the array is sorted. If {@code true}, the algorithm will be faster. * @return {@code true} if the array has duplicates, {@code false} otherwise */ public static boolean hasDuplicates(final float[] a, final boolean isSorted) { if (isEmpty(a)) { return false; } return hasDuplicates(a, 0, a.length, isSorted); } /** * Checks if the given array has duplicate elements within the specified range. * * @param a the array to be checked for duplicates * @param fromIndex The start index (inclusive) of the range to be checked * @param toIndex the end index (exclusive) of the range to be checked * @param isSorted a boolean that indicates if the array is sorted. If {@code true}, the algorithm will be faster. * @return {@code true} if the array has duplicates within the specified range, {@code false} otherwise * @throws IndexOutOfBoundsException if the range is out of bounds for the given array */ static boolean hasDuplicates(final float[] a, final int fromIndex, final int toIndex, final boolean isSorted) { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || toIndex - fromIndex < 2) { return false; } else if (toIndex - fromIndex == 2) { return equals(a[fromIndex], a[fromIndex + 1]); } else if (toIndex - fromIndex == 3) { return equals(a[fromIndex], a[fromIndex + 1]) || equals(a[fromIndex], a[fromIndex + 2]) || equals(a[fromIndex + 1], a[fromIndex + 2]); } if (isSorted) { for (int i = fromIndex + 1; i < toIndex; i++) { if (equals(a[i], a[i - 1])) { return true; } } } else { final Set set = newHashSet(toIndex - fromIndex); for (int i = fromIndex; i < toIndex; i++) { if (!set.add(a[i])) { return true; } } } return false; } /** * Checks if the given array has duplicate elements. * * @param a the array to be checked for duplicates * @return {@code true} if the array has duplicates, {@code false} otherwise */ public static boolean hasDuplicates(final double[] a) { return hasDuplicates(a, false); } /** * Checks if the given array has duplicate elements. * * @param a the array to be checked for duplicates * @param isSorted a boolean that indicates if the array is sorted. If {@code true}, the algorithm will be faster. * @return {@code true} if the array has duplicates, {@code false} otherwise */ public static boolean hasDuplicates(final double[] a, final boolean isSorted) { if (isEmpty(a)) { return false; } return hasDuplicates(a, 0, a.length, isSorted); } /** * Checks if the given array has duplicate elements within the specified range. * * @param a the array to be checked for duplicates * @param fromIndex The start index (inclusive) of the range to be checked * @param toIndex the end index (exclusive) of the range to be checked * @param isSorted a boolean that indicates if the array is sorted. If {@code true}, the algorithm will be faster. * @return {@code true} if the array has duplicates within the specified range, {@code false} otherwise * @throws IndexOutOfBoundsException if the range is out of bounds for the given array */ static boolean hasDuplicates(final double[] a, final int fromIndex, final int toIndex, final boolean isSorted) { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || toIndex - fromIndex < 2) { return false; } else if (toIndex - fromIndex == 2) { return equals(a[fromIndex], a[fromIndex + 1]); } else if (toIndex - fromIndex == 3) { return equals(a[fromIndex], a[fromIndex + 1]) || equals(a[fromIndex], a[fromIndex + 2]) || equals(a[fromIndex + 1], a[fromIndex + 2]); } if (isSorted) { for (int i = fromIndex + 1; i < toIndex; i++) { if (equals(a[i], a[i - 1])) { return true; } } } else { final Set set = newHashSet(toIndex - fromIndex); for (int i = fromIndex; i < toIndex; i++) { if (!set.add(a[i])) { return true; } } } return false; } /** * Checks if the given array has duplicate elements. * * @param * @param a the array to be checked for duplicates * @return {@code true} if the array has duplicates, {@code false} otherwise */ public static boolean hasDuplicates(final T[] a) { return hasDuplicates(a, false); } /** * Checks if the given array has duplicate elements. * * @param * @param a the array to be checked for duplicates * @param isSorted a boolean that indicates if the array is sorted. If {@code true}, the algorithm will be faster. * @return {@code true} if the array has duplicates, {@code false} otherwise */ public static boolean hasDuplicates(final T[] a, final boolean isSorted) { if (isEmpty(a)) { return false; } return hasDuplicates(a, 0, a.length, isSorted); } /** * Checks if the given array has duplicate elements within the specified range. * * @param a the array to be checked for duplicates * @param fromIndex The start index (inclusive) of the range to be checked * @param toIndex the end index (exclusive) of the range to be checked * @param isSorted a boolean that indicates if the array is sorted. If {@code true}, the algorithm will be faster. * @return {@code true} if the array has duplicates within the specified range, {@code false} otherwise * @throws IndexOutOfBoundsException if the range is out of bounds for the given array */ static boolean hasDuplicates(final T[] a, final int fromIndex, final int toIndex, final boolean isSorted) { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || toIndex - fromIndex < 2) { return false; } else if (toIndex - fromIndex == 2) { return equals(a[fromIndex], a[fromIndex + 1]); } else if (toIndex - fromIndex == 3) { return equals(a[fromIndex], a[fromIndex + 1]) || equals(a[fromIndex], a[fromIndex + 2]) || equals(a[fromIndex + 1], a[fromIndex + 2]); } if (isSorted) { for (int i = fromIndex + 1; i < toIndex; i++) { if (equals(a[i], a[i - 1])) { return true; } } } else { final Set set = newHashSet(toIndex - fromIndex); for (int i = fromIndex; i < toIndex; i++) { if (!set.add(hashKey(a[i]))) { return true; } } } return false; } /** * Checks if the given collection has duplicate elements. * * @param c the collection to be checked for duplicates * @return {@code true} if the collection has duplicates, {@code false} otherwise */ public static boolean hasDuplicates(final Collection c) { return hasDuplicates(c, false); } /** * Checks if the given collection has duplicate elements. * * @param c the collection to be checked for duplicates * @param isSorted a boolean that indicates if the collection is sorted. If {@code true}, the algorithm will be faster * @return {@code true} if the collection has duplicates, {@code false} otherwise */ public static boolean hasDuplicates(final Collection c, final boolean isSorted) { if (isEmpty(c) || c.size() == 1) { return false; } if (isSorted) { final Iterator it = c.iterator(); Object pre = it.next(); Object next = null; while (it.hasNext()) { next = it.next(); if (equals(next, pre)) { return true; } pre = next; } } else { final Set set = newHashSet(c.size()); for (final Object e : c) { if (!set.add(hashKey(e))) { return true; } } } return false; } /** * Retains only the elements in the specified collection that are present in the specified collection of elements to keep. * In other words, removes from the first collection all of its elements that are not contained in the second collection. * * @param the type of elements in the input collections * @param c the collection to be modified. * @param objsToKeep the collection containing elements to be retained in the first collection. * @return {@code true} if the first collection changed as a result of the call * @see Collection#retainAll(Collection) */ public static boolean retainAll(final Collection c, final Collection objsToKeep) { if (isEmpty(c)) { return false; } else if (isEmpty(objsToKeep)) { c.clear(); return true; } if (c instanceof HashSet && !(objsToKeep instanceof Set) && (c.size() > 9 || objsToKeep.size() > 9)) { return c.retainAll(newHashSet(objsToKeep)); } else { return c.retainAll(objsToKeep); } } /** * * @param obj * @return */ static Object hashKey(final Object obj) { return obj == null ? NULL_MASK : (obj.getClass().isArray() ? Wrapper.of(obj) : obj); } /** * Sums all elements in the given array of characters. * * @param a The array of characters to be summed. * @return The sum of all characters in the array. If the array is {@code null} or empty, {@code 0} is returned. */ @SafeVarargs public static int sum(final char... a) { if (isEmpty(a)) { return 0; } return sum(a, 0, a.length); } /** * Sums all elements within the specified range in the input array of characters * * @param a The array of characters to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @return The sum of all elements within the specified range in the input array. If the array is {@code null} or empty, {@code 0} is returned. * @throws IndexOutOfBoundsException If the specified range is out of bounds for the given array. */ public static int sum(final char[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0; } int sum = 0; for (int i = fromIndex; i < toIndex; i++) { sum += a[i]; } return sum; } /** * Sums all elements in the given array of bytes. * * @param a The array of bytes to be summed. * @return The sum of all bytes in the array. If the array is {@code null} or empty, {@code 0} is returned. */ @SafeVarargs public static int sum(final byte... a) { if (isEmpty(a)) { return 0; } return sum(a, 0, a.length); } /** * Sums all elements within the specified range in the input array of bytes * * @param a The array of bytes to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @return The sum of all elements within the specified range in the input array. If the array is {@code null} or empty, {@code 0} is returned. * @throws IndexOutOfBoundsException If the specified range is out of bounds for the given array. */ public static int sum(final byte[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0; } int sum = 0; for (int i = fromIndex; i < toIndex; i++) { sum += a[i]; } return sum; } /** * Sums all elements in the given array of shorts. * * @param a The array of shorts to be summed. * @return The sum of all shorts in the array. If the array is {@code null} or empty, {@code 0} is returned. */ @SafeVarargs public static int sum(final short... a) { if (isEmpty(a)) { return 0; } return sum(a, 0, a.length); } /** * Sums all elements within the specified range in the input array of shorts * * @param a The array of shorts to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @return The sum of all elements within the specified range in the input array. If the array is {@code null} or empty, {@code 0} is returned. * @throws IndexOutOfBoundsException If the specified range is out of bounds for the given array. */ public static int sum(final short[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0; } int sum = 0; for (int i = fromIndex; i < toIndex; i++) { sum += a[i]; } return sum; } /** * Sums all elements in the given array of ints. * * @param a The array of ints to be summed. * @return The sum of all ints in the array. If the array is {@code null} or empty, {@code 0} is returned */ @SafeVarargs public static int sum(final int... a) { if (isEmpty(a)) { return 0; } return sum(a, 0, a.length); } /** * Sums all elements within the specified range in the input array of ints * * @param a The array of ints to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @return The sum of all elements within the specified range in the input array. If the array is {@code null} or empty, {@code 0} is returned. * @throws IndexOutOfBoundsException If the specified range is out of bounds for the given array. */ public static int sum(final int[] a, final int fromIndex, final int toIndex) { return Numbers.toIntExact(sumToLong(a, fromIndex, toIndex)); } /** * Sums all elements in the given array of ints to a long value. * * @param a The array of longs to be summed. * @return The sum of all ints in the array. If the array is {@code null} or empty, {@code 0} is returned. */ @SafeVarargs public static long sumToLong(final int... a) { if (isEmpty(a)) { return 0; } return sumToLong(a, 0, a.length); } /** * Sums all elements within the specified range in the input array of ints to a long value. * * @param a The array of ints to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @return The sum of all elements within the specified range in the input array. If the array is {@code null} or empty, {@code 0} is returned. * @throws IndexOutOfBoundsException If the specified range is out of bounds for the given array. */ public static long sumToLong(final int[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0; } long sum = 0; for (int i = fromIndex; i < toIndex; i++) { sum += a[i]; } return Numbers.toIntExact(sum); } /** * Sums all elements in the given array of longs. * * @param a The array of longs to be summed. * @return The sum of all longs in the array. If the array is {@code null} or empty, {@code 0} is returned. */ @SafeVarargs public static long sum(final long... a) { if (isEmpty(a)) { return 0L; } return sum(a, 0, a.length); } /** * Sums all elements within the specified range in the input array of longs * * @param a The array of longs to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @return The sum of all elements within the specified range in the input array. If the array is {@code null} or empty, {@code 0} is returned. * @throws IndexOutOfBoundsException If the specified range is out of bounds for the given array. */ public static long sum(final long[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0; } long sum = 0; for (int i = fromIndex; i < toIndex; i++) { sum += a[i]; } return sum; } /** * Sums all elements in the given array of floats. * * @param a The array of floats to be summed. * @return The sum of all floats in the array. If the array is {@code null} or empty, {@code 0} is returned. */ @SafeVarargs public static float sum(final float... a) { if (isEmpty(a)) { return 0f; } return sum(a, 0, a.length); } /** * Sums all elements within the specified range in the input array of floats * * @param a The array of floats to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @return The sum of all elements within the specified range in the input array. If the array is {@code null} or empty, {@code 0} is returned. * @throws IndexOutOfBoundsException If the specified range is out of bounds for the given array. */ public static float sum(final float[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0f; } final KahanSummation summation = new KahanSummation(); for (int i = fromIndex; i < toIndex; i++) { summation.add(a[i]); } return (float) summation.sum(); } /** * Sums all elements in the given array of floats to a double value. * * @param a The array of floats to be summed. * @return The sum of all floats in the array. If the array is {@code null} or empty, {@code 0} is returned. */ @SafeVarargs public static double sumToDouble(final float... a) { if (isEmpty(a)) { return 0f; } return sumToDouble(a, 0, a.length); } /** * Sums all elements within the specified range in the input array of floats to a double value. * * @param a The array of floats to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @return The sum of all elements within the specified range in the input array. If the array is {@code null} or empty, {@code 0} is returned. * @throws IndexOutOfBoundsException If the specified range is out of bounds for the given array. */ public static double sumToDouble(final float[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0f; } final KahanSummation summation = new KahanSummation(); for (int i = fromIndex; i < toIndex; i++) { summation.add(a[i]); } return summation.sum(); } /** * Sums all elements in the given array of doubles. * * @param a The array of doubles to be summed. * @return The sum of all doubles in the array. If the array is {@code null} or empty, {@code 0} is returned. */ @SafeVarargs public static double sum(final double... a) { if (isEmpty(a)) { return 0d; } return sum(a, 0, a.length); } /** * Sums all elements within the specified range in the input array of doubles * * @param a The array of doubles to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @return The sum of all elements within the specified range in the input array. If the array is {@code null} or empty, {@code 0} is returned. * @throws IndexOutOfBoundsException If the specified range is out of bounds for the given array. */ public static double sum(final double[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0d; } final KahanSummation summation = new KahanSummation(); for (int i = fromIndex; i < toIndex; i++) { summation.add(a[i]); } return summation.sum(); } /** * Calculates the average of all elements in the given array of characters. * * @param a The array of characters to be averaged. * @return The average of all characters in the array. If the array is {@code null} or empty, {@code 0} is returned. */ @SafeVarargs public static double average(final char... a) { if (isEmpty(a)) { return 0d; } return average(a, 0, a.length); } /** * Calculates the average of all elements within the specified range in the given array of characters. * * @param a The array of characters to be averaged. * @param fromIndex The starting index, inclusive. * @param toIndex The ending index, exclusive. * @return The average of all characters in the specified range of the array. If the specified range is empty, {@code 0} is returned. * @throws IndexOutOfBoundsException If the specified range is out of bounds. */ public static double average(final char[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0d; } return ((double) sum(a, fromIndex, toIndex)) / (toIndex - fromIndex); } /** * Calculates the average of all elements in the given array of bytes. * * @param a The array of bytes to be averaged. * @return The average of all bytes in the array. If the array is {@code null} or empty, {@code 0} is returned. */ @SafeVarargs public static double average(final byte... a) { if (isEmpty(a)) { return 0d; } return average(a, 0, a.length); } /** * Calculates the average of all elements within the specified range in the given array of bytes. * * @param a The array of bytes to be averaged. * @param fromIndex The starting index, inclusive. * @param toIndex The ending index, exclusive. * @return The average of all bytes in the specified range of the array. If the specified range is empty, {@code 0} is returned. * @throws IndexOutOfBoundsException If the specified range is out of bounds. */ public static double average(final byte[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0d; } return ((double) sum(a, fromIndex, toIndex)) / (toIndex - fromIndex); } /** * Calculates the average of all elements in the given array of shorts. * * @param a The array of shorts to be averaged. * @return The average of all shorts in the array. If the array is {@code null} or empty, {@code 0} is returned. */ @SafeVarargs public static double average(final short... a) { if (isEmpty(a)) { return 0d; } return average(a, 0, a.length); } /** * Calculates the average of all elements within the specified range in the given array of shorts. * * @param a The array of shorts to be averaged. * @param fromIndex The starting index, inclusive. * @param toIndex The ending index, exclusive. * @return The average of all shorts in the specified range of the array. If the specified range is empty, {@code 0} is returned. * @throws IndexOutOfBoundsException If the specified range is out of bounds. */ public static double average(final short[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0d; } return ((double) sum(a, fromIndex, toIndex)) / (toIndex - fromIndex); } /** * Calculates the average of all elements in the given array of ints. * * @param a The array of ints to be averaged. * @return The average of all ints in the array. If the array is {@code null} or empty, {@code 0} is returned. */ @SafeVarargs public static double average(final int... a) { if (isEmpty(a)) { return 0d; } return average(a, 0, a.length); } /** * Calculates the average of all elements within the specified range in the given array of ints. * * @param a The array of ints to be averaged. * @param fromIndex The starting index, inclusive. * @param toIndex The ending index, exclusive. * @return The average of all ints in the specified range of the array. If the specified range is empty, {@code 0} is returned. * @throws IndexOutOfBoundsException If the specified range is out of bounds. */ public static double average(final int[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0d; } long sum = 0; for (int i = fromIndex; i < toIndex; i++) { sum += a[i]; } return ((double) sum) / (toIndex - fromIndex); } /** * Calculates the average of all elements in the given array of longs. * * @param a The array of longs to be averaged. * @return The average of all longs in the array. If the array is {@code null} or empty, {@code 0} is returned. */ @SafeVarargs public static double average(final long... a) { if (isEmpty(a)) { return 0d; } return average(a, 0, a.length); } /** * Calculates the average of all elements within the specified range in the given array of longs. * * @param a The array of longs to be averaged. * @param fromIndex The starting index, inclusive. * @param toIndex The ending index, exclusive. * @return The average of all longs in the specified range of the array. If the specified range is empty, {@code 0} is returned. * @throws IndexOutOfBoundsException If the specified range is out of bounds. */ public static double average(final long[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0d; } return ((double) sum(a, fromIndex, toIndex)) / (toIndex - fromIndex); } /** * Calculates the average of all elements in the given array of floats. * * @param a The array of floats to be averaged. * @return The average of all floats in the array. If the array is {@code null} or empty, {@code 0} is returned. */ @SafeVarargs public static double average(final float... a) { if (isEmpty(a)) { return 0d; } return average(a, 0, a.length); } /** * Calculates the average of all elements within the specified range in the given array of floats. * * @param a The array of floats to be averaged. * @param fromIndex The starting index, inclusive. * @param toIndex The ending index, exclusive. * @return The average of all floats in the specified range of the array. If the specified range is empty, {@code 0} is returned. * @throws IndexOutOfBoundsException If the specified range is out of bounds. */ public static double average(final float[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0d; } final KahanSummation summation = new KahanSummation(); for (int i = fromIndex; i < toIndex; i++) { summation.add(a[i]); } return summation.average().orElseZero(); } /** * Calculates the average of all elements in the given array of doubles. * * @param a The array of doubles to be averaged. * @return The average of all doubles in the array. If the array is {@code null} or empty, {@code 0} is returned */ @SafeVarargs public static double average(final double... a) { if (isEmpty(a)) { return 0d; } return average(a, 0, a.length); } /** * Calculates the average of all elements within the specified range in the given array of doubles. * * @param a The array of doubles to be averaged. * @param fromIndex The starting index, inclusive. * @param toIndex The ending index, exclusive. * @return The average of all doubles in the specified range of the array. If the specified range is empty, {@code 0} is returned. * @throws IndexOutOfBoundsException If the specified range is out of bounds. */ public static double average(final double[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0d; } final KahanSummation summation = new KahanSummation(); for (int i = fromIndex; i < toIndex; i++) { summation.add(a[i]); } return summation.average().orElseZero(); } /** * Sums all elements in the given array of numbers and returns the result as an integer. * * @param The type of the elements in the array, which must extend Number. * @param a The array of numbers to be summed. * @return The sum of all elements in the array as an integer. * @see Iterables#sumInt(Iterable) */ public static int sumInt(final T[] a) { return sumInt(a, Fn.numToInt()); } /** * Sums all elements within the specified range in the input array of numbers and returns the result as an integer. * * @param The type of the elements in the array, which must extend Number. * @param a The array of numbers to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @return The sum of all elements within the specified range in the array as an integer. * @throws IndexOutOfBoundsException If the specified range is out of bounds for the given array. * @see Iterables#sumInt(Iterable) */ public static int sumInt(final T[] a, final int fromIndex, final int toIndex) { return sumInt(a, fromIndex, toIndex, Fn.numToInt()); } /** * Sums all elements in the given array using the provided function to convert each element to an integer. * * @param The type of the elements in the array. * @param a The array of elements to be summed. * @param func The function to convert each element to an integer. * @return The sum of all elements in the array as an integer. * @see Iterables#sumInt(Iterable, ToIntFunction) */ public static int sumInt(final T[] a, final ToIntFunction func) throws IndexOutOfBoundsException { if (isEmpty(a)) { return 0; } return sumInt(a, 0, a.length, func); } /** * Sums all elements within the specified range in the input array using the provided function to convert each element to an integer. * * @param The type of the elements in the array. * @param a The array of elements to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @param func The function to convert each element to an integer. * @return The sum of all elements within the specified range of the array as an integer. * @throws IndexOutOfBoundsException If the specified range is out of bounds. * @see Iterables#sumInt(Iterable, ToIntFunction) */ public static int sumInt(final T[] a, final int fromIndex, final int toIndex, final ToIntFunction func) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (fromIndex == toIndex) { return 0; } long sum = 0; for (int i = fromIndex; i < toIndex; i++) { sum += func.applyAsInt(a[i]); } return Numbers.toIntExact(sum); } /** * Sums all elements within the specified range in the input collection of numbers and returns the result as an integer. * * @param The type of the elements in the collection, which must extend Number. * @param c The collection of numbers to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @return The sum of all elements within the specified range in the collection as an integer. * @throws IndexOutOfBoundsException If the specified range is out of bounds for the given collection. * @see Iterables#sumInt(Iterable) */ public static int sumInt(final Collection c, final int fromIndex, final int toIndex) { return sumInt(c, fromIndex, toIndex, Fn.numToInt()); } /** * Sums all elements within the specified range in the input collection using the provided function to convert each element to an integer. * * @param The type of the elements in the collection. * @param c The collection of elements to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @param func The function to convert each element to an integer. * @return The sum of all elements within the specified range of the collection as an integer. * @throws IndexOutOfBoundsException If the specified range is out of bounds. * @see Iterables#sumInt(Iterable, ToIntFunction) */ public static int sumInt(final Collection c, final int fromIndex, final int toIndex, final ToIntFunction func) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); if (fromIndex == toIndex) { return 0; } long sum = 0; if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; for (int i = fromIndex; i < toIndex; i++) { sum += func.applyAsInt(list.get(i)); } } else { int idx = 0; for (final T e : c) { if (idx++ < fromIndex) { continue; } sum += func.applyAsInt(e); if (idx >= toIndex) { break; } } } return Numbers.toIntExact(sum); } /** * Sums all elements in the given iterable of numbers and returns the result as a integer. * * @param The type of the elements in the iterable, which must extend Number. * @param c The iterable of elements to be summed. * @return The sum of all elements in the iterable as a integer. * @see Iterables#sumInt(Iterable) */ public static int sumInt(final Iterable c) { return sumInt(c, Fn.numToInt()); } /** * Sums all elements in the given iterable using the provided function to convert each element to an integer. * * @param The type of the elements in the iterable. * @param c The iterable of elements to be summed. * @param func The function to convert each element to an integer. * @return The sum of all elements in the iterable as an integer. * @see Iterables#sumInt(Iterable, ToIntFunction) */ public static int sumInt(final Iterable c, final ToIntFunction func) { return Numbers.toIntExact(sumIntToLong(c, func)); } /** * Sums all elements in the given iterable of numbers and returns the result as a long. * * @param The type of the elements in the iterable, which must extend Number. * @param c The iterable of numbers to be summed. * @return The sum of all elements in the iterable as a long. * @see Iterables#sumLong(Iterable) */ public static long sumIntToLong(final Iterable c) { return sumIntToLong(c, Fn.numToInt()); } /** * Sums all elements in the given iterable using the provided function to convert each element to an integer and returns the result as a long. * * @param The type of the elements in the iterable. * @param c The iterable of elements to be summed. * @param func The function to convert each element to an integer. * @return The sum of all elements in the iterable as a long. * @see Iterables#sumIntToLong(Iterable, ToIntFunction) */ public static long sumIntToLong(final Iterable c, final ToIntFunction func) { if (isEmptyCollection(c)) { return 0; } long sum = 0; for (final T e : c) { sum += func.applyAsInt(e); } return sum; } /** * Sums all elements in the given array of numbers and returns the result as a long. * * @param The type of the elements in the array, which must extend Number. * @param a The array of numbers to be summed. * @return The sum of all elements in the array as a long. * @see Iterables#sumLong(Iterable) */ public static long sumLong(final T[] a) { return sumLong(a, Fn.numToLong()); } /** * Sums all elements within the specified range in the input array of numbers and returns the result as a long. * * @param The type of the elements in the array, which must extend Number. * @param a The array of numbers to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @return The sum of all elements within the specified range in the array as a long. * @throws IndexOutOfBoundsException If the specified range is out of bounds for the given array. * @see Iterables#sumLong(Iterable) */ public static long sumLong(final T[] a, final int fromIndex, final int toIndex) { return sumLong(a, fromIndex, toIndex, Fn.numToLong()); } /** * Sums all elements in the given array using the provided function to convert each element to a long. * * @param The type of the elements in the array. * @param a The array of elements to be summed. * @param func The function to convert each element to a long. * @return The sum of all elements in the array as a long. * @see Iterables#sumLong(Iterable, ToLongFunction) */ public static long sumLong(final T[] a, final ToLongFunction func) throws IndexOutOfBoundsException { if (isEmpty(a)) { return 0L; } return sumLong(a, 0, a.length, func); } /** * Sums all elements within the specified range in the input array using the provided function to convert each element to a long. * * @param The type of the elements in the array. * @param a The array of elements to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @param func The function to convert each element to a long. * @return The sum of all elements within the specified range of the array as a long. * @throws IndexOutOfBoundsException If the specified range is out of bounds. * @see Iterables#sumLong(Iterable, ToLongFunction) */ public static long sumLong(final T[] a, final int fromIndex, final int toIndex, final ToLongFunction func) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (fromIndex == toIndex) { return 0L; } long sum = 0; for (int i = fromIndex; i < toIndex; i++) { sum += func.applyAsLong(a[i]); } return sum; } /** * Sums all elements within the specified range in the input collection of numbers and returns the result as an long. * * @param The type of the elements in the collection, which must extend Number. * @param c The collection of numbers to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @return The sum of all elements within the specified range in the collection as an long. * @throws IndexOutOfBoundsException If the specified range is out of bounds for the given collection. * @see Iterables#sumLong(Iterable) */ public static long sumLong(final Collection c, final int fromIndex, final int toIndex) { return sumLong(c, fromIndex, toIndex, Fn.numToLong()); } /** * Sums all elements within the specified range in the input collection using the provided function to convert each element to a long. * * @param The type of the elements in the collection. * @param c The collection of elements to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @param func The function to convert each element to a long. * @return The sum of all elements within the specified range of the collection as a long. * @throws IndexOutOfBoundsException If the specified range is out of bounds. * @see Iterables#sumLong(Iterable, ToLongFunction) */ public static long sumLong(final Collection c, final int fromIndex, final int toIndex, final ToLongFunction func) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); if (fromIndex == toIndex) { return 0L; } long sum = 0; if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; for (int i = fromIndex; i < toIndex; i++) { sum += func.applyAsLong(list.get(i)); } } else { int idx = 0; for (final T e : c) { if (idx++ < fromIndex) { continue; } sum += func.applyAsLong(e); if (idx >= toIndex) { break; } } } return sum; } /** * Sums all elements in the given iterable of numbers and returns the result as a long. * * @param The type of the elements in the iterable, which must extend Number. * @param c The iterable of numbers to be summed. * @return The sum of all elements in the iterable as a long. * @see Iterables#sumLong(Iterable) */ public static long sumLong(final Iterable c) { return sumLong(c, Fn.numToLong()); } /** * Sums all elements in the given iterable using the provided function to convert each element to a long. * * @param The type of the elements in the iterable. * @param c The iterable of elements to be summed. * @param func The function to convert each element to a long. * @return The sum of all elements in the iterable as a long. * @see Iterables#sumLong(Iterable, ToLongFunction) */ public static long sumLong(final Iterable c, final ToLongFunction func) { if (isEmptyCollection(c)) { return 0L; } long sum = 0; for (final T e : c) { sum += func.applyAsLong(e); } return sum; } /** * Sums all elements in the given array of numbers and returns the result as a double. * * @param The type of the elements in the array, which must extend Number. * @param a The array of numbers to be summed. * @return The sum of all elements in the array as a double. * @see Iterables#sumDouble(Iterable) */ public static double sumDouble(final T[] a) { return sumDouble(a, Fn.numToDouble()); } /** * Sums all elements within the specified range in the input array of numbers and returns the result as a double. * * @param The type of the elements in the array, which must extend Number. * @param a The array of numbers to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @return The sum of all elements within the specified range in the array as a double. * @throws IndexOutOfBoundsException If the specified range is out of bounds for the given array. * @see Iterables#sumDouble(Iterable) */ public static double sumDouble(final T[] a, final int fromIndex, final int toIndex) { return sumDouble(a, fromIndex, toIndex, Fn.numToDouble()); } /** * Sums all elements in the given array using the provided function to convert each element to a double. * * @param The type of the elements in the array. * @param a The array of elements to be summed. * @param func The function to convert each element to a double. * @return The sum of all elements in the array as a double. * @see Iterables#sumDouble(Iterable, ToDoubleFunction) */ public static double sumDouble(final T[] a, final ToDoubleFunction func) { if (isEmpty(a)) { return 0D; } return sumDouble(a, 0, a.length, func); } /** * Sums all elements within the specified range in the input array using the provided function to convert each element to a double. * * @param The type of the elements in the array. * @param a The array of elements to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @param func The function to convert each element to a double. * @return The sum of all elements within the specified range of the array as a double. * @throws IndexOutOfBoundsException If the specified range is out of bounds. * @see Iterables#sumDouble(Iterable, ToDoubleFunction) */ public static double sumDouble(final T[] a, final int fromIndex, final int toIndex, final ToDoubleFunction func) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (fromIndex == toIndex) { return 0D; } final KahanSummation summation = new KahanSummation(); for (int i = fromIndex; i < toIndex; i++) { summation.add(func.applyAsDouble(a[i])); } return summation.sum(); } /** * Sums all elements within the specified range in the input collection of numbers and returns the result as an double. * * @param The type of the elements in the collection, which must extend Number. * @param c The collection of numbers to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @return The sum of all elements within the specified range in the collection as an double. * @throws IndexOutOfBoundsException If the specified range is out of bounds for the given collection. * @see Iterables#sumDouble(Iterable) */ public static double sumDouble(final Collection c, final int fromIndex, final int toIndex) { return sumDouble(c, fromIndex, toIndex, Fn.numToDouble()); } /** * Sums all elements within the specified range in the input collection using the provided function to convert each element to a double. * * @param The type of the elements in the collection. * @param c The collection of elements to be summed. * @param fromIndex The starting index (inclusive) of the range to be summed. * @param toIndex The ending index (exclusive) of the range to be summed. * @param func The function to convert each element to a double. * @return The sum of all elements within the specified range of the collection as a double. * @throws IndexOutOfBoundsException If the specified range is out of bounds. * @see Iterables#sumDouble(Iterable, ToDoubleFunction) */ public static double sumDouble(final Collection c, final int fromIndex, final int toIndex, final ToDoubleFunction func) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); if (fromIndex == toIndex) { return 0D; } final KahanSummation summation = new KahanSummation(); if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; for (int i = fromIndex; i < toIndex; i++) { summation.add(func.applyAsDouble(list.get(i))); } } else { int idx = 0; for (final T e : c) { if (idx++ < fromIndex) { continue; } summation.add(func.applyAsDouble(e)); if (idx >= toIndex) { break; } } } return summation.sum(); } /** * Sums all elements in the given iterable of numbers and returns the result as a double. * * @param The type of the elements in the iterable, which must extend Number. * @param c The iterable of numbers to be summed. * @return The sum of all elements in the iterable as a double. * @see Iterables#sumDouble(Iterable) */ public static double sumDouble(final Iterable c) { return sumDouble(c, Fn.numToDouble()); } /** * Sums all elements in the given iterable using the provided function to convert each element to a double. * * @param The type of the elements in the iterable. * @param c The iterable of elements to be summed. * @param func The function to convert each element to a double. * @return The sum of all elements in the iterable as a double. * @see Iterables#sumDouble(Iterable, ToDoubleFunction) */ public static double sumDouble(final Iterable c, final ToDoubleFunction func) { if (isEmptyCollection(c)) { return 0D; } final Iterator iter = c.iterator(); final KahanSummation summation = new KahanSummation(); while (iter.hasNext()) { summation.add(func.applyAsDouble(iter.next())); } return summation.sum(); } /** * Sums all elements in the given iterable of BigInteger and returns the result as a BigInteger. * * @param c The iterable of BigInteger elements to be summed. * @return The sum of all elements in the iterable as a BigInteger. * @see Iterables#sumBigInteger(Iterable) */ public static BigInteger sumBigInteger(final Iterable c) { return sumBigInteger(c, Fn.identity()); } /** * Sums all elements in the given iterable using the provided function to convert each element to a BigInteger. * * @param The type of elements in the iterable. * @param c The iterable of elements to be summed. * @param func The function to convert each element to a BigInteger. * @return The sum of all elements in the iterable as a BigInteger. * @see Iterables#sumBigInteger(Iterable, Function) */ public static BigInteger sumBigInteger(final Iterable c, final Function func) { if (isEmptyCollection(c)) { return BigInteger.ZERO; } final Iterator iter = c.iterator(); BigInteger result = BigInteger.ZERO; BigInteger next = null; while (iter.hasNext()) { next = func.apply(iter.next()); if (next != null) { result = result.add(next); } } return result; } /** * Sums all elements in the given iterable of BigDecimal and returns the result as a BigDecimal. * * @param c The iterable of BigDecimal elements to be summed. * @return The sum of all elements in the iterable as a BigDecimal. * @see Iterables#sumBigDecimal(Iterable) */ public static BigDecimal sumBigDecimal(final Iterable c) { return sumBigDecimal(c, Fn.identity()); } /** * Sums all elements in the given iterable using the provided function to convert each element to a BigDecimal. * * @param The type of elements in the iterable. * @param c The iterable of elements to be summed. * @param func The function to convert each element to a BigDecimal. * @return The sum of all elements in the iterable as a BigDecimal. * @see Iterables#sumBigDecimal(Iterable, Function) */ public static BigDecimal sumBigDecimal(final Iterable c, final Function func) { if (isEmptyCollection(c)) { return BigDecimal.ZERO; } final Iterator iter = c.iterator(); BigDecimal result = BigDecimal.ZERO; BigDecimal next = null; while (iter.hasNext()) { next = func.apply(iter.next()); if (next != null) { result = result.add(next); } } return result; } /** * Calculates the average of the elements in the given array of numbers. * * @param The type of the elements in the array, which must extend Number. * @param a The array of numbers to calculate the average. * @return The average of the elements in the array as a double. * @see Iterables#averageInt(Number[]) */ public static double averageInt(final T[] a) { return averageInt(a, Fn.numToInt()); } /** * Calculates the average of the elements in the given array of numbers within the specified range. * * @param The type of the elements in the array, which must extend Number. * @param a The array of numbers to calculate the average. * @param fromIndex The starting index (inclusive) of the range. * @param toIndex The ending index (exclusive) of the range. * @return The average of the elements within the specified range as a double. * @throws IndexOutOfBoundsException if the specified range is out of bounds. * @see Iterables#averageInt(Number[], int, int) */ public static double averageInt(final T[] a, final int fromIndex, final int toIndex) { return averageInt(a, fromIndex, toIndex, Fn.numToInt()); } /** * Calculates the average of the elements in the given array using the provided function to convert each element to an integer. * * @param The type of the elements in the array * @param a The array of numbers to calculate the average. * @param func The function to convert each element to an integer. * @return The average of the elements in the array as a double. * @see Iterables#averageInt(Object[], ToIntFunction) */ public static double averageInt(final T[] a, final ToIntFunction func) { if (isEmpty(a)) { return 0d; } return averageInt(a, 0, a.length, func); } /** * Calculates the average of the elements within the specified range in the input array using the provided function to convert each element to an integer. * * @param The type of the elements in the array * @param a The array to calculate the average. * @param fromIndex The starting index (inclusive) of the range. * @param toIndex The ending index (exclusive) of the range. * @param func The function to convert each element to an integer. * @return The average of the elements within the specified range as a double. * @throws IndexOutOfBoundsException if the specified range is out of bounds. * @see Iterables#averageInt(Object[], int, int, ToIntFunction) */ public static double averageInt(final T[] a, final int fromIndex, final int toIndex, final ToIntFunction func) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (fromIndex == toIndex) { return 0d; } long sum = 0; for (int i = fromIndex; i < toIndex; i++) { sum += func.applyAsInt(a[i]); } return ((double) sum) / (toIndex - fromIndex); } /** * Calculates the average of the elements within the specified range in the input collection of numbers. * * @param The type of the elements in the collection, which must extend Number. * @param c The collection of numbers to calculate the average. * @param fromIndex The starting index (inclusive) of the range. * @param toIndex The ending index (exclusive) of the range. * @return The average of the elements within the specified range as a double. * @throws IndexOutOfBoundsException if the specified range is out of bounds. * @see Iterables#averageInt(Collection, int, int) */ public static double averageInt(final Collection c, final int fromIndex, final int toIndex) { return averageInt(c, fromIndex, toIndex, Fn.numToInt()); } /** * Calculates the average of the elements within the specified range in the input collection using the provided function to convert each element to an integer. * * @param The type of the elements in the collection * @param c The collection to calculate the average. * @param fromIndex The starting index (inclusive) of the range. * @param toIndex The ending index (exclusive) of the range. * @param func The function to convert each element to an integer. * @return The average of the elements within the specified range as a double. * @throws IndexOutOfBoundsException if the specified range is out of bounds. * @see Iterables#averageInt(Collection, int, int, ToIntFunction) */ public static double averageInt(final Collection c, final int fromIndex, final int toIndex, final ToIntFunction func) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); if (fromIndex == toIndex) { return 0; } long sum = 0; if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; for (int i = fromIndex; i < toIndex; i++) { sum += func.applyAsInt(list.get(i)); } } else { int idx = 0; for (final T e : c) { if (idx++ < fromIndex) { continue; } sum += func.applyAsInt(e); if (idx >= toIndex) { break; } } } return ((double) sum) / (toIndex - fromIndex); } /** * Calculates the average of the elements in the given iterable of numbers. * * @param The type of the elements in the iterable, which must extend Number. * @param c The iterable of numbers to calculate the average. * @return The average of the elements in the iterable as a double. * @see Iterables#averageInt(Iterable) */ public static double averageInt(final Iterable c) { return averageInt(c, Fn.numToInt()); } /** * Calculates the average of the elements in the given iterable using the provided function to convert each element to an integer. * * @param The type of the elements in the iterable. * @param c The iterable of elements to calculate the average. * @param func The function to convert each element to an integer. * @return The average of the elements in the iterable as a double. * @see Iterables#averageInt(Iterable, ToIntFunction) */ public static double averageInt(final Iterable c, final ToIntFunction func) { if (isEmptyCollection(c)) { return 0D; } long sum = 0; long count = 0; for (final T e : c) { sum += func.applyAsInt(e); count++; } return count == 0 ? 0D : ((double) sum) / count; } /** * Calculates the average of the elements in the given array of numbers. * * @param The type of the elements in the array, which must extend Number. * @param a The array of numbers to calculate the average. * @return The average of the elements in the array as a double. * @see Iterables#averageLong(Number[]) */ public static double averageLong(final T[] a) { return averageLong(a, Fn.numToLong()); } /** * Calculates the average of the elements within the specified range in the input array of numbers. * * @param The type of the elements in the array, which must extend Number. * @param a The array of numbers to calculate the average. * @param fromIndex The starting index (inclusive) of the range. * @param toIndex The ending index (exclusive) of the range. * @return The average of the elements within the specified range as a double. * @throws IndexOutOfBoundsException if the specified range is out of bounds. * @see Iterables#averageLong(Number[], int, int) */ public static double averageLong(final T[] a, final int fromIndex, final int toIndex) { return averageLong(a, fromIndex, toIndex, Fn.numToLong()); } /** * Calculates the average of the elements in the given array using the provided function to convert each element to a long. * * @param The type of the elements in the array * @param a The array of numbers to calculate the average. * @param func The function to convert each element to a long. * @return The average of the elements in the array as a double. * @see Iterables#averageLong(Object[], ToLongFunction) */ public static double averageLong(final T[] a, final ToLongFunction func) { if (isEmpty(a)) { return 0d; } return averageLong(a, 0, a.length, func); } /** * Calculates the average of the elements within the specified range in the input array using the provided function to convert each element to a long. * * @param The type of the elements in the array * @param a The array of numbers to calculate the average. * @param fromIndex The starting index (inclusive) of the range. * @param toIndex The ending index (exclusive) of the range. * @param func The function to convert each element to a long. * @return The average of the elements within the specified range as a double. * @throws IndexOutOfBoundsException if the specified range is out of bounds. * @see Iterables#averageLong(Object[], int, int, ToLongFunction) */ public static double averageLong(final T[] a, final int fromIndex, final int toIndex, final ToLongFunction func) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (fromIndex == toIndex) { return 0d; } return ((double) sumLong(a, fromIndex, toIndex, func)) / (toIndex - fromIndex); } /** * Calculates the average of the elements in the given collection of numbers. * * @param The type of the elements in the collection, which must extend Number. * @param c The collection of numbers to calculate the average. * @return The average of the elements in the collection as a double. * @see Iterables#averageLong(Collection, int, int) */ public static double averageLong(final Collection c, final int fromIndex, final int toIndex) { return averageLong(c, fromIndex, toIndex, Fn.numToLong()); } /** * Calculates the average of the elements within the specified range in the input collection using the provided function to convert each element to a long. * * @param The type of the elements in the collection * @param c The collection to calculate the average. * @param fromIndex The starting index (inclusive) of the range. * @param toIndex The ending index (exclusive) of the range. * @param func The function to convert each element to a long. * @return The average of the elements within the specified range as a double. * @throws IndexOutOfBoundsException if the specified range is out of bounds. * @see Iterables#averageLong(Collection, int, int, ToLongFunction) */ public static double averageLong(final Collection c, final int fromIndex, final int toIndex, final ToLongFunction func) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); if (fromIndex == toIndex) { return 0d; } return ((double) sumLong(c, fromIndex, toIndex, func)) / (toIndex - fromIndex); } /** * Calculates the average of the elements in the given iterable of numbers. * * @param The type of the elements in the iterable, which must extend Number. * @param c The iterable of numbers to calculate the average. * @return The average of the elements in the iterable as a double. * @see Iterables#averageLong(Iterable) */ public static double averageLong(final Iterable c) { return averageLong(c, Fn.numToLong()); } /** * Calculates the average of the elements in the given iterable using the provided function to convert each element to a long. * * @param The type of the elements in the iterable. * @param c The iterable of elements to calculate the average. * @param func The function to convert each element to a long. * @return The average of the elements in the iterable as a double. * @see Iterables#averageLong(Iterable, ToLongFunction) */ public static double averageLong(final Iterable c, final ToLongFunction func) { if (isEmptyCollection(c)) { return 0D; } long sum = 0; long count = 0; for (final T e : c) { sum += func.applyAsLong(e); count++; } return count == 0 ? 0D : ((double) sum) / count; } /** * Calculates the average of the elements in the given array of numbers. * * @param The type of the elements in the array, which must extend Number. * @param a The array of numbers to calculate the average. * @return The average of the elements in the array as a double. * @see Iterables#averageDouble(Number[]) */ public static double averageDouble(final T[] a) { return averageDouble(a, Fn.numToDouble()); } /** * Calculates the average of the elements within the specified range in the input array of numbers. * * @param The type of the elements in the array, which must extend Number. * @param a The array of numbers to calculate the average. * @param fromIndex The starting index (inclusive) of the range. * @param toIndex The ending index (exclusive) of the range. * @return The average of the elements within the specified range as a double. * @throws IndexOutOfBoundsException if the specified range is out of bounds. * @see Iterables#averageDouble(Number[], int, int) */ public static double averageDouble(final T[] a, final int fromIndex, final int toIndex) { return averageDouble(a, fromIndex, toIndex, Fn.numToDouble()); } /** * Calculates the average of the elements in the given array using the provided function to convert each element to a double. * * @param The type of the elements in the array * @param a The array to calculate the average. * @param func The function to convert each element to a double. * @return The average of the elements in the array as a double. * @see Iterables#averageDouble(Object[], ToDoubleFunction) */ public static double averageDouble(final T[] a, final ToDoubleFunction func) { if (isEmpty(a)) { return 0d; } return averageDouble(a, 0, a.length, func); } /** * Calculates the average of the elements within the specified range in the input array using the provided function to convert each element to a double. * * @param The type of the elements in the array * @param a The array to calculate the average. * @param fromIndex The starting index (inclusive) of the range. * @param toIndex The ending index (exclusive) of the range. * @param func The function to convert each element to a double. * @return The average of the elements within the specified range as a double. * @throws IndexOutOfBoundsException if the specified range is out of bounds. * @see Iterables#averageDouble(Object[], int, int, ToDoubleFunction) */ public static double averageDouble(final T[] a, final int fromIndex, final int toIndex, final ToDoubleFunction func) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (fromIndex == toIndex) { return 0d; } return Iterables.averageDouble(a, fromIndex, toIndex, func).orElseZero(); } /** * Calculates the average of the elements in the given collection of numbers. * * @param The type of the elements in the collection, which must extend Number. * @param c The collection of numbers to calculate the average. * @return The average of the elements in the collection as a double. * @see Iterables#averageDouble(Collection, int, int) */ public static double averageDouble(final Collection c, final int fromIndex, final int toIndex) { return averageDouble(c, fromIndex, toIndex, Fn.numToDouble()); } /** * Calculates the average of the elements within the specified range in the input collection using the provided function to convert each element to a double. * * @param The type of the elements in the collection * @param c The collection to calculate the average. * @param fromIndex The starting index (inclusive) of the range. * @param toIndex The ending index (exclusive) of the range. * @param func The function to convert each element to a double. * @return The average of the elements within the specified range as a double. * @throws IndexOutOfBoundsException if the specified range is out of bounds. * @see Iterables#averageDouble(Collection, int, int, ToDoubleFunction) */ public static double averageDouble(final Collection c, final int fromIndex, final int toIndex, final ToDoubleFunction func) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); if (fromIndex == toIndex) { return 0d; } return Iterables.averageDouble(c, fromIndex, toIndex, func).orElseZero(); } /** * Calculates the average of the elements in the given iterable of numbers. * * @param The type of the elements in the iterable, which must extend Number. * @param c The iterable of numbers to calculate the average. * @return The average of the elements in the iterable as a double. * @see Iterables#averageDouble(Iterable) */ public static double averageDouble(final Iterable c) { return averageDouble(c, Fn.numToDouble()); } /** * Calculates the average of the elements in the given iterable using the provided function to convert each element to a double. * * @param The type of the elements in the iterable. * @param c The iterable of elements to calculate the average. * @param func The function to convert each element to a double. * @return The average of the elements in the iterable as a double. * @see Iterables#averageDouble(Iterable, ToDoubleFunction) */ public static double averageDouble(final Iterable c, final ToDoubleFunction func) { if (isEmptyCollection(c)) { return 0d; } return Iterables.averageDouble(c, func).orElseZero(); } /** * Calculates the average of the elements in the given iterable of BigInteger. * * @param c The iterable of BigInteger elements to calculate the average. * @return The average of the elements in the iterable as a BigDecimal. * @see Iterables#averageBigInteger(Iterable) */ public static BigDecimal averageBigInteger(final Iterable c) { return averageBigInteger(c, Fn.identity()); } /** * Calculates the average of the elements in the given iterable using the provided function to convert each element to a BigInteger. * * @param The type of elements in the iterable. * @param c The iterable of elements to calculate the average. * @param func The function to convert each element to a BigInteger. * @return The average of the elements in the iterable as a BigDecimal. * @see Iterables#averageBigInteger(Iterable, Function) */ public static BigDecimal averageBigInteger(final Iterable c, final Function func) { if (isEmptyCollection(c)) { return BigDecimal.ZERO; } final Iterator iter = c.iterator(); BigInteger sum = BigInteger.ZERO; long cnt = 0; BigInteger next = null; while (iter.hasNext()) { next = func.apply(iter.next()); if (next != null) { sum = sum.add(next); cnt++; } } //noinspection BigDecimalMethodWithoutRoundingCalled return cnt == 0 ? BigDecimal.ZERO : new BigDecimal(sum).divide(BigDecimal.valueOf(cnt)); } /** * Calculates the average of the elements in the given iterable of BigDecimal. * * @param c The iterable of BigDecimal elements to calculate the average. * @return The average of the elements in the iterable as a BigDecimal. * @see Iterables#averageBigDecimal(Iterable) */ public static BigDecimal averageBigDecimal(final Iterable c) { return averageBigDecimal(c, Fn.identity()); } /** * Calculates the average of the elements in the given iterable using the provided function to convert each element to a BigDecimal. * * @param The type of elements in the iterable. * @param c The iterable of elements to calculate the average. * @param func The function to convert each element to a BigDecimal. * @return The average of the elements in the iterable as a BigDecimal. * @see Iterables#averageBigDecimal(Iterable, Function) */ public static BigDecimal averageBigDecimal(final Iterable c, final Function func) { if (isEmptyCollection(c)) { return BigDecimal.ZERO; } final Iterator iter = c.iterator(); BigDecimal sum = BigDecimal.ZERO; long cnt = 0; BigDecimal next = null; while (iter.hasNext()) { next = func.apply(iter.next()); if (next != null) { sum = sum.add(next); cnt++; } } //noinspection BigDecimalMethodWithoutRoundingCalled return cnt == 0 ? BigDecimal.ZERO : sum.divide(BigDecimal.valueOf(cnt)); } /** * Returns the smaller of two input char values. * * @param a the first char value. * @param b the second char value. * @return the smaller of two input char values. */ public static char min(final char a, final char b) { return (a <= b) ? a : b; } /** * Returns the smaller of two input byte values. * * @param a the first byte value. * @param b the second byte value. * @return the smaller of two input byte values. */ public static byte min(final byte a, final byte b) { return (a <= b) ? a : b; } /** * Returns the smaller of two input short values. * * @param a the first short value. * @param b the second short value. * @return the smaller of two input short values. */ public static short min(final short a, final short b) { return (a <= b) ? a : b; } /** * Returns the smaller of two input int values. * * @param a the first int value. * @param b the second int value. * @return the smaller of two input int values */ public static int min(final int a, final int b) { return Math.min(a, b); } /** * Returns the smaller of two input long values. * * @param a the first long value. * @param b the second long value. * @return the smaller of two input long values. */ public static long min(final long a, final long b) { return Math.min(a, b); } /** * Returns the smaller of two input float values. * * @param a the first float value. * @param b the second float value. * @return the smaller of two input float values. */ public static float min(final float a, final float b) { return Math.min(a, b); } /** * Returns the smaller of two input double values. * * @param a the first double value. * @param b the second double value. * @return the smaller of two input double values. */ public static double min(final double a, final double b) { return Math.min(a, b); } /** * Returns the smaller of two input comparable values. * * @param a the first comparable value. * @param b the second comparable value. * @return the smaller of two input comparable values. */ public static > T min(final T a, final T b) { return min(a, b, (Comparator) NULL_MAX_COMPARATOR); } /** * Returns the smaller of two input values based on the specified comparator. * * @param the type of the values * @param a the first value to compare * @param b the second value to compare * @param cmp the Comparator to compare the values * @return the smaller of two input values based on the specified comparator */ public static T min(final T a, final T b, final Comparator cmp) { if (cmp == null) { return ((Comparator) NULL_MAX_COMPARATOR).compare(a, b) <= 0 ? a : b; } else { return cmp.compare(a, b) <= 0 ? a : b; } } /** * Returns the smallest of the three input char values. * * @param a the first char value. * @param b the second char value. * @param c the third char value. * @return the smallest of the three input char values. */ public static char min(final char a, final char b, final char c) { final char m = (a <= b) ? a : b; return (m <= c) ? m : c; } /** * Returns the smallest of the three input byte values. * * @param a the first byte value. * @param b the second byte value. * @param c the third byte value. * @return the smallest of the three input byte values. */ public static byte min(final byte a, final byte b, final byte c) { final byte m = (a <= b) ? a : b; return (m <= c) ? m : c; } /** * Returns the smallest of the three input short values. * * @param a the first short value. * @param b the second short value. * @param c the third short value. * @return the smallest of the three input short values. */ public static short min(final short a, final short b, final short c) { final short m = (a <= b) ? a : b; return (m <= c) ? m : c; } /** * Returns the smallest of the three input int values. * * @param a the first int value. * @param b the second int value. * @param c the third int value. * @return the smallest of the three input int values. */ public static int min(final int a, final int b, final int c) { final int m = Math.min(a, b); return Math.min(m, c); } /** * Returns the smallest of the three input long values. * * @param a the first long value. * @param b the second long value. * @param c the third long value. * @return the smallest of the three input long values. */ public static long min(final long a, final long b, final long c) { final long m = Math.min(a, b); return Math.min(m, c); } /** * Returns the smallest of the three input float values. * * @param a the first float value. * @param b the second float value. * @param c the third float value. * @return the smallest of the three input float values. */ public static float min(final float a, final float b, final float c) { return Math.min(Math.min(a, b), c); } /** * Returns the smallest of the three input double values. * * @param a the first double value. * @param b the second double value. * @param c the third double value. * @return the smallest of the three input double values. */ public static double min(final double a, final double b, final double c) { return Math.min(Math.min(a, b), c); } /** * Returns the smallest of the three input comparable values. * * @param a the first comparable value. * @param b the second comparable value. * @param c the third comparable value. * @return the smallest of the three input comparable values. */ public static > T min(final T a, final T b, final T c) { return min(a, b, c, (Comparator) NULL_MAX_COMPARATOR); } /** * Returns the smallest of the three input values based on the specified comparator. * * @param the type of the values * @param a the first value to compare * @param b the second value to compare * @param c the third value to compare * @param cmp the Comparator to compare the values * @return the smallest of the three input values based on the specified comparator */ public static T min(final T a, final T b, final T c, final Comparator cmp) { return min(min(a, b, cmp), c, cmp); } /** * Returns the smallest char value in the specified array. * * @param a the array of char values to fetch the smallest value. * @return the smallest char value in the array. * @throws IllegalArgumentException if the array is {@code null} or empty. */ @SafeVarargs public static char min(final char... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); //NOSONAR if (isEmpty(a)) { throw new IllegalArgumentException("The specified array can not be null or empty"); } return min(a, 0, a.length); } /** * Returns the smallest char value within the specified range in the input array. * * @param a the array of char values to fetch the smallest value. * @param fromIndex the starting index (inclusive) of the range. * @param toIndex the ending index (exclusive) of the range. * @return the smallest char value within the specified range of the array. * @throws IllegalArgumentException if the specified array or range is empty. */ public static char min(final char[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } char min = a[fromIndex]; for (int i = fromIndex + 1; i < toIndex; i++) { if (a[i] < min) { min = a[i]; } } return min; } /** * Returns the smallest byte value in the specified array. * * @param a the array of byte values to fetch the smallest value. * @return the smallest byte value in the array. * @throws IllegalArgumentException if the array is {@code null} or empty. */ @SafeVarargs public static byte min(final byte... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return min(a, 0, a.length); } /** * Returns the smallest byte value within the specified range in the input array. * * @param a the array of byte values to fetch the smallest value. * @param fromIndex the starting index (inclusive) of the range. * @param toIndex the ending index (exclusive) of the range. * @return the smallest byte value within the specified range of the array. * @throws IllegalArgumentException if the specified array or range is empty. */ public static byte min(final byte[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } byte min = a[fromIndex]; for (int i = fromIndex + 1; i < toIndex; i++) { if (a[i] < min) { min = a[i]; } } return min; } /** * Returns the smallest short value in the specified array. * * @param a the array of short values to fetch the smallest value. * @return the smallest short value in the array. * @throws IllegalArgumentException if the array is {@code null} or empty. */ @SafeVarargs public static short min(final short... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return min(a, 0, a.length); } /** * Returns the smallest short value within the specified range in the input array. * * @param a the array of short values to fetch the smallest value. * @param fromIndex the starting index (inclusive) of the range. * @param toIndex the ending index (exclusive) of the range. * @return the smallest short value within the specified range of the array. * @throws IllegalArgumentException if the specified array or range is empty. */ public static short min(final short[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } short min = a[fromIndex]; for (int i = fromIndex + 1; i < toIndex; i++) { if (a[i] < min) { min = a[i]; } } return min; } /** * Returns the smallest int value in the specified array. * * @param a the array of int values to fetch the smallest value. * @return the smallest int value in the array. * @throws IllegalArgumentException if the array is {@code null} or empty. */ @SafeVarargs public static int min(final int... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return min(a, 0, a.length); } /** * Returns the smallest int value within the specified range in the input array. * * @param a the array of int values to fetch the smallest value. * @param fromIndex the starting index (inclusive) of the range. * @param toIndex the ending index (exclusive) of the range. * @return the smallest int value within the specified range of the array. * @throws IllegalArgumentException if the specified array or range is empty. */ public static int min(final int[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } int min = a[fromIndex]; for (int i = fromIndex + 1; i < toIndex; i++) { if (a[i] < min) { min = a[i]; } } return min; } /** * Returns the smallest long value in the specified array. * * @param a the array of long values to fetch the smallest value. * @return the smallest long value in the array. * @throws IllegalArgumentException if the array is {@code null} or empty. */ @SafeVarargs public static long min(final long... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return min(a, 0, a.length); } /** * Returns the smallest long value within the specified range in the input array. * * @param a the array of long values to fetch the smallest value. * @param fromIndex the starting index (inclusive) of the range. * @param toIndex the ending index (exclusive) of the range. * @return the smallest long value within the specified range of the array. * @throws IllegalArgumentException if the specified array or range is empty. */ public static long min(final long[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } long min = a[fromIndex]; for (int i = fromIndex + 1; i < toIndex; i++) { if (a[i] < min) { min = a[i]; } } return min; } /** * Returns the smallest float value in the specified array. * * @param a the array of float values to fetch the smallest value. * @return the smallest float value in the array. * @throws IllegalArgumentException if the array is {@code null} or empty. * @see IEEE754rUtil#min(float[]) that handles NaN differently */ @SafeVarargs public static float min(final float... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return min(a, 0, a.length); } /** * Returns the smallest float value within the specified range in the input array. * * @param a the array of float values to fetch the smallest value. * @param fromIndex the starting index (inclusive) of the range. * @param toIndex the ending index (exclusive) of the range. * @return the smallest float value within the specified range of the array. * @throws IllegalArgumentException if the specified array or range is empty. * @see IEEE754rUtil#min(float[]) that handles NaN differently */ public static float min(final float[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } float min = a[fromIndex]; for (int i = fromIndex + 1; i < toIndex; i++) { min = Math.min(min, a[i]); if (Float.isNaN(min)) { return min; } } return min; } /** * Returns the smallest double value in the specified array. * * @param a the array of double values to fetch the smallest value. * @return the smallest double value in the array. * @throws IllegalArgumentException if the array is {@code null} or empty. * @see IEEE754rUtil#min(double[]) that handles NaN differently */ @SafeVarargs public static double min(final double... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return min(a, 0, a.length); } /** * Returns the smallest double value within the specified range in the input array. * * @param a the array of double values to fetch the smallest value. * @param fromIndex the starting index (inclusive) of the range. * @param toIndex the ending index (exclusive) of the range. * @return the smallest double value within the specified range of the array. * @throws IllegalArgumentException if the specified array or range is empty. * @see IEEE754rUtil#min(double[]) that handles NaN differently */ public static double min(final double[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } double min = a[fromIndex]; for (int i = fromIndex + 1; i < toIndex; i++) { min = Math.min(min, a[i]); if (Double.isNaN(min)) { return min; } } return min; } /** * Returns the smallest value in the specified array based on their natural ordering. Null values are considered to be maximum here. * * @param a the array to fetch the smallest value. * @return the smallest value in the array. * @throws IllegalArgumentException if the array is {@code null} or empty. * @see Iterables#min(Comparable[]) */ public static > T min(final T[] a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return min(a, 0, a.length); } /** * Returns the smallest value within the specified range in the input array based on their natural ordering. Null values are considered to be maximum here. * * @param a the array to fetch the smallest value. * @param fromIndex the starting index (inclusive) of the range. * @param toIndex the ending index (exclusive) of the range. * @return the smallest value within the specified range of the array. * @throws IllegalArgumentException if the specified array or range is empty. * @see Iterables#min(Object[], Comparator) */ public static > T min(final T[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException { return min(a, fromIndex, toIndex, (Comparator) NULL_MAX_COMPARATOR); } /** * Returns the smallest value in the specified array according to the provided comparator. * * @param the type of elements in the input array. * @param a the array to fetch the smallest value. * @param cmp the comparator to be used to compare the elements * @return the smallest value in the array. * @throws IllegalArgumentException if the array is {@code null} or empty. * @see Iterables#min(Object[], Comparator) */ public static T min(final T[] a, final Comparator cmp) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return min(a, 0, a.length, cmp); } /** * Returns the smallest value within the specified range in the input array according to the provided comparator. * * @param the type of elements in the input array. * @param a the array to fetch the smallest value. * @param fromIndex the starting index (inclusive) of the range. * @param toIndex the ending index (exclusive) of the range. * @param cmp the comparator to be used to compare the elements * @return the smallest value within the specified range of the array. * @throws IllegalArgumentException if the specified array or range is empty. * @see Iterables#min(Object[], Comparator) */ public static T min(final T[] a, final int fromIndex, final int toIndex, Comparator cmp) throws IndexOutOfBoundsException, IllegalArgumentException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } cmp = cmp == null ? (Comparator) NULL_MAX_COMPARATOR : cmp; T candidate = a[fromIndex]; for (int i = fromIndex + 1; i < toIndex; i++) { if (cmp.compare(a[i], candidate) < 0) { candidate = a[i]; } if (candidate == null && cmp == NULL_MIN_COMPARATOR) { // NOSONAR return null; } } return candidate; } /** * Returns the smallest value within the specified range in the input collection based on their natural ordering. Null values are considered to be maximum here. * * @param c the collection to fetch the smallest value. * @param fromIndex the starting index (inclusive) of the range. * @param toIndex the ending index (exclusive) of the range. * @return the smallest value within the specified range of the collection. * @throws IllegalArgumentException if the specified collection or range is empty. * @see Iterables#min(Iterable) */ public static > T min(final Collection c, final int fromIndex, final int toIndex) throws IllegalArgumentException { checkArgNotEmpty(c, "The specified collection can not be null or empty"); return min(c, fromIndex, toIndex, (Comparator) NULL_MAX_COMPARATOR); } /** * Returns the smallest value within the specified range in the input collection according to the provided comparator. * * @param c the collection to fetch the smallest value. * @param fromIndex the starting index (inclusive) of the range. * @param toIndex the ending index (exclusive) of the range. * @param cmp the comparator to be used to compare the elements * @return the smallest value within the specified range of the collection. * @throws IllegalArgumentException if the specified collection or range is empty. * @see Iterables#min(Iterable, Comparator) */ public static T min(final Collection c, final int fromIndex, final int toIndex, Comparator cmp) throws IllegalArgumentException { checkFromToIndex(fromIndex, toIndex, size(c)); if (isEmpty(c) || toIndex - fromIndex < 1 || fromIndex >= c.size()) { throw new IllegalArgumentException("The size of collection can not be null or empty"); } cmp = cmp == null ? (Comparator) NULL_MAX_COMPARATOR : cmp; T candidate = null; T e = null; if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; candidate = list.get(fromIndex); for (int i = fromIndex + 1; i < toIndex; i++) { e = list.get(i); if (cmp.compare(e, candidate) < 0) { candidate = e; } if (candidate == null && cmp == NULL_MIN_COMPARATOR) { // NOSONAR return null; } } } else { final Iterator it = c.iterator(); for (int i = 0; i < toIndex; i++) { if (i < fromIndex) { it.next(); } else if (i == fromIndex) { candidate = it.next(); } else { e = it.next(); if (cmp.compare(e, candidate) < 0) { candidate = e; } if (candidate == null && cmp == NULL_MIN_COMPARATOR) { // NOSONAR return null; } } } } return candidate; } /** * Returns the smallest value in the specified iterable based on their natural ordering. Null values are considered to be maximum here. * * @param the type of elements in the input iterable. * @param c the iterable to fetch the smallest value. * @return the smallest value in the iterable. * @throws IllegalArgumentException if the specified iterable is {@code null} or empty. * @see Iterables#min(Iterable) */ public static > T min(final Iterable c) throws IllegalArgumentException { return min(c, (Comparator) NULL_MAX_COMPARATOR); } /** * Returns the smallest value in the specified iterable according to the provided comparator. * * @param the type of elements in the input iterable. * @param c the iterable to fetch the smallest value. * @param cmp the comparator to be used to compare the elements * @return the smallest value in the iterable. * @throws IllegalArgumentException if the specified iterable is {@code null} or empty. * @see Iterables#min(Iterable, Comparator) */ public static T min(final Iterable c, final Comparator cmp) throws IllegalArgumentException { if (c instanceof Collection) { final Collection coll = (Collection) c; return min(coll, 0, coll.size(), cmp); } final Iterator iter = Iterables.iterateNonEmpty(c, "The specified Collection/Iterable/Iterator can not be null or empty"); //NOSONAR return min(iter, cmp); } /** * Returns the smallest value in the specified iterator based on their natural ordering. Null values are considered to be maximum here. * * @param the type of elements in the input iterator. * @param iter the iterator to fetch the smallest value. * @return the smallest value in the iterator. * @throws IllegalArgumentException if the iterator is {@code null} or empty. * @see Iterables#min(Iterator) */ public static > T min(final Iterator iter) throws IllegalArgumentException { return min(iter, (Comparator) NULL_MAX_COMPARATOR); } /** * Returns the smallest value in the specified iterator according to the provided comparator. * * @param the type of elements in the input iterator. * @param iter the iterator to fetch the smallest value. * @param cmp the comparator to be used to compare the elements * @return the smallest value in the iterator. * @throws IllegalArgumentException if the specified iterator is {@code null} or empty. * @see Iterables#min(Iterator, Comparator) */ public static T min(final Iterator iter, Comparator cmp) throws IllegalArgumentException { checkArgument(!isEmpty(iter), "The specified Collection/Iterable/Iterator can not be null or empty"); cmp = cmp == null ? (Comparator) NULL_MAX_COMPARATOR : cmp; T candidate = iter.next(); T e = null; while (iter.hasNext()) { e = iter.next(); if (cmp.compare(e, candidate) < 0) { candidate = e; } if (candidate == null && cmp == NULL_MIN_COMPARATOR) { // NOSONAR return null; } } return candidate; } /** * Returns a list containing the smallest elements in the specified array based on their natural ordering. Null values are considered to be maximum here. * * @param the type of elements in the input array. * @param a the array to fetch the smallest elements. * @return a list containing the smallest elements in the array. If the array is {@code null} or empty, an empty list is returned. */ public static > List minAll(final T[] a) { return minAll(a, NULL_MAX_COMPARATOR); } /** * Returns a list containing the smallest elements in the specified array according to the provided comparator. * * @param the type of elements in the array. * @param a the array to fetch the smallest elements. * @param cmp the comparator to be used to compare the elements * @return a list containing the smallest elements in the array. If the array is {@code null} or empty, an empty list is returned. */ public static List minAll(final T[] a, Comparator cmp) { if (isEmpty(a)) { return new ArrayList<>(); } cmp = cmp == null ? (Comparator) NULL_MAX_COMPARATOR : cmp; final List result = new ArrayList<>(); T candidate = a[0]; int cp = 0; result.add(candidate); for (int i = 1, len = a.length; i < len; i++) { cp = cmp.compare(a[i], candidate); if (cp == 0) { result.add(a[i]); } else if (cp < 0) { result.clear(); result.add(a[i]); candidate = a[i]; } } return result; } /** * Returns a list containing the smallest elements in the specified iterable based on their natural ordering. Null values are considered to be maximum here. * * @param the type of elements in the input iterable. * @param c the iterable to fetch the smallest elements. * @return a list containing the smallest elements in the iterable. If the iterable is {@code null} or empty, an empty list is returned. */ public static > List minAll(final Iterable c) { return minAll(c, NULL_MAX_COMPARATOR); } /** * Returns a list containing the smallest elements in the specified iterable according to the provided comparator. * * @param the type of elements in the input iterable. * @param c the iterable to fetch the smallest elements. * @param cmp the comparator to be used to compare the elements * @return a list containing the smallest elements in the iterable. If the iterable is {@code null} or empty, an empty list is returned. */ public static List minAll(final Iterable c, final Comparator cmp) { if (isEmptyCollection(c)) { return new ArrayList<>(); } return minAll(c.iterator(), cmp); } /** * Returns a list containing the smallest elements in the specified iterator based on their natural ordering. Null values are considered to be maximum here. * * @param the type of elements in the input iterator. * @param iter the iterator to fetch the smallest elements. * @return a list containing the smallest elements in the iterator. If the iterator is {@code null} or empty, an empty list is returned. */ public static > List minAll(final Iterator iter) { return maxAll(iter, NULL_MAX_COMPARATOR); } /** * Returns a list containing the smallest elements in the specified iterator according to the provided comparator. * * @param the type of elements in the input iterator. * @param iter the iterator to fetch the smallest elements. * @param cmp the comparator to be used to compare the elements * @return a list containing the smallest elements in the iterator. If the iterator is {@code null} or empty, an empty list is returned. */ public static List minAll(final Iterator iter, Comparator cmp) { cmp = cmp == null ? (Comparator) NULL_MAX_COMPARATOR : cmp; final List result = new ArrayList<>(); T candidate = iter.next(); T next = null; int cp = 0; result.add(candidate); while (iter.hasNext()) { next = iter.next(); cp = cmp.compare(next, candidate); if (cp == 0) { result.add(next); } else if (cp < 0) { result.clear(); result.add(next); candidate = next; } } return result; } /** * Returns the minimum value extracted from the specified array or a default value if the array is {@code null} or empty. Null values are considered to be maximum here. * * @param the type of elements in the input array. * @param the type of the extracted value, which must be comparable. * @param a the array to extract the minimum value from. * @param valueExtractor the function to extract values from the array elements for comparison. * @param defaultValue the default value to return if the array is {@code null} or empty. * @return the minimum extracted value or the default value if the array is {@code null} or empty. */ @Beta public static > R minOrDefaultIfEmpty(final T[] a, final Function valueExtractor, final R defaultValue) { if (isEmpty(a)) { return defaultValue; } R candidate = valueExtractor.apply(a[0]); R next = null; for (int i = 1, len = a.length; i < len; i++) { next = valueExtractor.apply(a[i]); if (candidate == null || (next != null && (next.compareTo(candidate) < 0))) { candidate = next; } } return candidate; } /** * Returns the minimum value extracted from the specified iterable or a default value if the iterable is {@code null} or empty. Null values are considered to be maximum here. * * @param the type of elements in the input iterable. * @param the type of the extracted value, which must be comparable. * @param c the iterable to extract the minimum value from. * @param valueExtractor the function to extract values from the iterable elements for comparison. * @param defaultValue the default value to return if the iterable is {@code null} or empty. * @return the minimum extracted value or the default value if the iterable is {@code null} or empty. */ public static > R minOrDefaultIfEmpty(final Iterable c, final Function valueExtractor, final R defaultValue) { if (isEmptyCollection(c)) { return defaultValue; } return minOrDefaultIfEmpty(c.iterator(), valueExtractor, defaultValue); } /** * Returns the minimum value extracted from the specified iterator or a default value if the iterator is {@code null} or empty. Null values are considered to be maximum here. * * @param the type of elements in the input iterator. * @param the type of the extracted value, which must be comparable. * @param iter the iterator to extract the minimum value from. * @param valueExtractor the function to extract values from the iterator elements for comparison. * @param defaultValue the default value to return if the iterator is {@code null} or empty. * @return the minimum extracted value or the default value if the iterator is {@code null} or empty. */ public static > R minOrDefaultIfEmpty(final Iterator iter, final Function valueExtractor, final R defaultValue) { if (iter == null || !iter.hasNext()) { return defaultValue; } R candidate = valueExtractor.apply(iter.next()); R next = null; while (iter.hasNext()) { next = valueExtractor.apply(iter.next()); if (candidate == null || (next != null && (next.compareTo(candidate) < 0))) { candidate = next; } } return candidate; } /** * Returns the minimum integer value extracted from the array or a default value if the array is {@code null} or empty. * * @param the type of elements in the input array. * @param a the array to extract the minimum integer from. * @param valueExtractor the function to extract integer values from the array elements. * @param defaultValue the default value to return if the array is {@code null} or empty. * @return the minimum extracted integer value or the default value if the array is {@code null} or empty. */ @Beta public static int minIntOrDefaultIfEmpty(final T[] a, final ToIntFunction valueExtractor, final int defaultValue) { if (isEmpty(a)) { return defaultValue; } int candidate = valueExtractor.applyAsInt(a[0]); int next = 0; for (int i = 1, len = a.length; i < len; i++) { next = valueExtractor.applyAsInt(a[i]); if (next < candidate) { candidate = next; } } return candidate; } /** * Returns the minimum integer value extracted from the specified iterable or a default value if the iterable is {@code null} or empty. * * @param the type of elements in the input iterable. * @param c the iterable to extract the minimum integer from. * @param valueExtractor the function to extract integer values from the iterable elements. * @param defaultValue the default value to return if the iterable is {@code null} or empty. * @return the minimum extracted integer value or the default value if the iterable is {@code null} or empty. */ @Beta public static int minIntOrDefaultIfEmpty(final Iterable c, final ToIntFunction valueExtractor, final int defaultValue) { if (isEmptyCollection(c)) { return defaultValue; } return minIntOrDefaultIfEmpty(c.iterator(), valueExtractor, defaultValue); } /** * Returns the minimum integer value extracted from the specified iterator or a default value if the iterator is {@code null} or empty. * * @param the type of elements in the input iterator. * @param iter the iterator to extract the minimum integer from. * @param valueExtractor the function to extract integer values from the iterator elements. * @param defaultValue the default value to return if the iterator is {@code null} or empty. * @return the minimum extracted integer value or the default value if the iterator is {@code null} or empty. */ @Beta public static int minIntOrDefaultIfEmpty(final Iterator iter, final ToIntFunction valueExtractor, final int defaultValue) { if (iter == null || !iter.hasNext()) { return defaultValue; } int candidate = valueExtractor.applyAsInt(iter.next()); int next = 0; while (iter.hasNext()) { next = valueExtractor.applyAsInt(iter.next()); if (next < candidate) { candidate = next; } } return candidate; } /** * Returns the minimum long value extracted from the specified array or a default value if the array is {@code null} or empty. * * @param the type of elements in the input array. * @param a the array to extract the minimum long from. * @param valueExtractor the function to extract long values from the array elements. * @param defaultValue the default value to return if the array is {@code null} or empty. * @return the minimum extracted long value or the default value if the array is {@code null} or empty. */ @Beta public static long minLongOrDefaultIfEmpty(final T[] a, final ToLongFunction valueExtractor, final long defaultValue) { if (isEmpty(a)) { return defaultValue; } long candidate = valueExtractor.applyAsLong(a[0]); long next = 0; for (int i = 1, len = a.length; i < len; i++) { next = valueExtractor.applyAsLong(a[i]); if (next < candidate) { candidate = next; } } return candidate; } /** * Returns the minimum long value extracted from the specified iterable or a default value if the iterable is {@code null} or empty. * * @param the type of elements in the input iterable. * @param c the iterable to extract the minimum long from. * @param valueExtractor the function to extract long values from the iterable elements. * @param defaultValue the default value to return if the iterable is {@code null} or empty. * @return the minimum extracted long value or the default value if the iterable is {@code null} or empty. */ @Beta public static long minLongOrDefaultIfEmpty(final Iterable c, final ToLongFunction valueExtractor, final long defaultValue) { if (isEmptyCollection(c)) { return defaultValue; } return minLongOrDefaultIfEmpty(c.iterator(), valueExtractor, defaultValue); } /** * Returns the minimum long value extracted from the specified iterator or a default value if the iterator is {@code null} or empty. * * @param the type of elements in the input iterator. * @param iter the iterator to extract the minimum long from. * @param valueExtractor the function to extract long values from the iterator elements. * @param defaultValue the default value to return if the iterator is {@code null} or empty. * @return the minimum extracted long value or the default value if the iterator is {@code null} or empty. */ @Beta public static long minLongOrDefaultIfEmpty(final Iterator iter, final ToLongFunction valueExtractor, final long defaultValue) { if (iter == null || !iter.hasNext()) { return defaultValue; } long candidate = valueExtractor.applyAsLong(iter.next()); long next = 0; while (iter.hasNext()) { next = valueExtractor.applyAsLong(iter.next()); if (next < candidate) { candidate = next; } } return candidate; } /** * Returns the minimum double value extracted from the specified array or a default value if the array is {@code null} or empty. * * @param the type of elements in the input array. * @param a the array to extract the minimum double from. * @param valueExtractor the function to extract double values from the array elements. * @param defaultValue the default value to return if the array is {@code null} or empty. * @return the minimum extracted double value or the default value if the array is {@code null} or empty. */ @Beta public static double minDoubleOrDefaultIfEmpty(final T[] a, final ToDoubleFunction valueExtractor, final double defaultValue) { if (isEmpty(a)) { return defaultValue; } double candidate = valueExtractor.applyAsDouble(a[0]); double next = 0; for (int i = 1, len = a.length; i < len; i++) { next = valueExtractor.applyAsDouble(a[i]); if (compare(next, candidate) < 0) { candidate = next; } } return candidate; } /** * Returns the minimum double value extracted from the specified iterable or a default value if the iterable is {@code null} or empty. * * @param the type of elements in the input iterable. * @param c the iterable to extract the minimum double from. * @param valueExtractor the function to extract double values from the iterable elements. * @param defaultValue the default value to return if the iterable is {@code null} or empty. * @return the minimum extracted double value or the default value if the iterable is {@code null} or empty. */ @Beta public static double minDoubleOrDefaultIfEmpty(final Iterable c, final ToDoubleFunction valueExtractor, final double defaultValue) { if (isEmptyCollection(c)) { return defaultValue; } return minDoubleOrDefaultIfEmpty(c.iterator(), valueExtractor, defaultValue); } /** * Returns the minimum double value extracted from the specified iterator or a default value if the iterator is {@code null} or empty. * * @param the type of elements in the input iterator. * @param iter the iterator to extract the minimum double from. * @param valueExtractor the function to extract double values from the iterator elements. * @param defaultValue the default value to return if the iterator is {@code null} or empty. * @return the minimum extracted double value or the default value if the iterator is {@code null} or empty. */ @Beta public static double minDoubleOrDefaultIfEmpty(final Iterator iter, final ToDoubleFunction valueExtractor, final double defaultValue) { if (iter == null || !iter.hasNext()) { return defaultValue; } double candidate = valueExtractor.applyAsDouble(iter.next()); double next = 0; while (iter.hasNext()) { next = valueExtractor.applyAsDouble(iter.next()); if (compare(next, candidate) < 0) { candidate = next; } } return candidate; } /** * Returns a Pair object containing the minimum and maximum values in the specified array based on their natural ordering. Null values are considered to be minimum here. * * @param the type of elements in the input array, which must be comparable. * @param a the array to find the minimum and maximum values from. * @return a Pair object where the first element is the minimum value and the second element is the maximum value in the specified array. * @throws IllegalArgumentException if the array is {@code null} or empty. * @see Iterables#minMax(Comparable[]) */ public static > Pair minMax(final T[] a) throws IllegalArgumentException { return minMax(a, NATURAL_COMPARATOR); } /** * Returns a Pair object containing the minimum and maximum values in the specified array according to the provided comparator. * * @param the type of elements in the input array. * @param a the array to find the minimum and maximum values from. * @param cmp the comparator to be used to compare the elements * @return a Pair object where the first element is the minimum value and the second element is the maximum value in the specified array. * @throws IllegalArgumentException if the array is {@code null} or empty. * @see Iterables#minMax(Object[], Comparator) */ public static Pair minMax(final T[] a, Comparator cmp) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); if (a.length == 1) { return Pair.of(a[0], a[0]); } cmp = checkComparator(cmp); T min = a[0]; T max = a[0]; int cp = 0; for (int i = 1, len = a.length; i < len; i++) { cp = cmp.compare(a[i], min); if (cp < 0) { min = a[i]; } else if ((cp > 0) && (cmp.compare(a[i], max) > 0)) { max = a[i]; } } return Pair.of(min, max); } /** * Returns a Pair object containing the minimum and maximum values in the specified iterable based on their natural ordering. Null values are considered to be minimum here. * * @param the type of elements in the input iterable, which must be comparable. * @param c the iterable to find the minimum and maximum values from. * @return a Pair object where the first element is the minimum value and the second element is the maximum value in the specified iterable. * @throws IllegalArgumentException if the iterable is {@code null} or empty. * @see Iterables#minMax(Iterable) */ public static > Pair minMax(final Iterable c) throws IllegalArgumentException { return minMax(c, NATURAL_COMPARATOR); } /** * Returns a Pair object containing the minimum and maximum values in the specified iterable according to the provided comparator. * * @param the type of elements in the input iterable. * @param c the iterable to find the minimum and maximum values from. * @param cmp the comparator to be used to compare the elements * @return a Pair object where the first element is the minimum value and the second element is the maximum value in the specified iterable. * @throws IllegalArgumentException if the iterable is {@code null} or empty. * @see Iterables#minMax(Iterable, Comparator) */ public static Pair minMax(@NotNull final Iterable c, final Comparator cmp) throws IllegalArgumentException { checkArgNotNull(c, "The specified iterable can not be null or empty"); return minMax(c.iterator(), cmp); } /** * Returns a Pair object containing the minimum and maximum values in the specified iterator based on their natural ordering. Null values are considered to be minimum here. * * @param the type of elements in the input iterator, which must be comparable. * @param iter the iterator to find the minimum and maximum values from. * @return a Pair object where the first element is the minimum value and the second element is the maximum value in the specified iterator. * @throws IllegalArgumentException if the iterator is {@code null} or empty. * @see Iterables#minMax(Iterator) */ public static > Pair minMax(final Iterator iter) throws IllegalArgumentException { return minMax(iter, NATURAL_COMPARATOR); } /** * Returns a Pair object containing the minimum and maximum values in the specified iterator according to the provided comparator. * * @param the type of elements in the input iterator. * @param iter the iterator to find the minimum and maximum values from. * @param cmp the comparator to be used to compare the elements * @return a Pair object where the first element is the minimum value and the second element is the maximum value in the specified iterator. * @throws IllegalArgumentException if the iterator is {@code null} or empty. * @see Iterables#minMax(Iterator, Comparator) */ public static Pair minMax(final Iterator iter, Comparator cmp) throws IllegalArgumentException { checkArgument(iter != null && iter.hasNext(), "The specified iterator can not be null or empty"); cmp = checkComparator(cmp); T next = iter.next(); T min = next; T max = next; int cp = 0; while (iter.hasNext()) { next = iter.next(); cp = cmp.compare(next, min); if (cp < 0) { min = next; } else if ((cp > 0) && (cmp.compare(next, max) > 0)) { max = next; } } return Pair.of(min, max); } /** * Returns the bigger of two char values. * * @param a the first char value. * @param b the second char value. * @return the bigger of the two char values. */ public static char max(final char a, final char b) { return (a >= b) ? a : b; } /** * Returns the bigger of two byte values. * * @param a the first byte value. * @param b the second byte value. * @return the bigger of the two byte values. */ public static byte max(final byte a, final byte b) { return (a >= b) ? a : b; } /** * Returns the bigger of two short values. * * @param a the first short value. * @param b the second short value. * @return the bigger of the two short values. */ public static short max(final short a, final short b) { return (a >= b) ? a : b; } /** * Returns the bigger of two int values. * * @param a the first int value. * @param b the second int value. * @return the bigger of the two int values. */ public static int max(final int a, final int b) { return Math.max(a, b); } /** * Returns the bigger of two long values. * * @param a the first long value. * @param b the second long value. * @return the bigger of the two long values. */ public static long max(final long a, final long b) { return Math.max(a, b); } /** * Returns the bigger of two float values. * * @param a the first float value. * @param b the second float value. * @return the bigger of the two float values. */ public static float max(final float a, final float b) { return Math.max(a, b); } /** * Returns the bigger of two double values. * * @param a the first double value. * @param b the second double value. * @return the bigger of the two double values. */ public static double max(final double a, final double b) { return Math.max(a, b); } /** * Returns the bigger value of the two provided values based on their natural ordering. Null values are considered to be minimum here. * * @param the type of the objects being compared, which must be comparable. * @param a the first object to compare. * @param b the second object to compare. * @return the bigger value of the two provided values. */ public static > T max(final T a, final T b) { return max(a, b, (Comparator) NULL_MIN_COMPARATOR); } /** * Returns the bigger value of the two provided values according to the provided comparator. * * @param the type of the objects being compared. * @param a the first object to compare. * @param b the second object to compare. * @param cmp the comparator to be used to compare the objects * @return the bigger value of the two provided values. */ public static T max(final T a, final T b, final Comparator cmp) { if (cmp == null) { return ((Comparator) NULL_MIN_COMPARATOR).compare(a, b) >= 0 ? a : b; } else { return cmp.compare(a, b) >= 0 ? a : b; } } /** * Returns the biggest value among the provided values. * * @param a the first char value. * @param b the second char value. * @param c the third char value. * @return the biggest value among the provided values. */ public static char max(final char a, final char b, final char c) { final char m = (a >= b) ? a : b; return (m >= c) ? m : c; } /** * Returns the biggest value among the provided values. * * @param a the first byte value. * @param b the second byte value. * @param c the third byte value. * @return the biggest value among the provided values. */ public static byte max(final byte a, final byte b, final byte c) { final byte m = (a >= b) ? a : b; return (m >= c) ? m : c; } /** * Returns the biggest value among the provided values. * * @param a the first short value. * @param b the second short value. * @param c the third short value. * @return the biggest value among the provided values. */ public static short max(final short a, final short b, final short c) { final short m = (a >= b) ? a : b; return (m >= c) ? m : c; } /** * Returns the biggest value among the provided values. * * @param a the first int value. * @param b the second int value. * @param c the third int value. * @return the biggest value among the provided values. */ public static int max(final int a, final int b, final int c) { final int m = Math.max(a, b); return Math.max(m, c); } /** * Returns the biggest value among the provided values. * * @param a the first long value. * @param b the second long value. * @param c the third long value. * @return the biggest value among the provided values. */ public static long max(final long a, final long b, final long c) { final long m = Math.max(a, b); return Math.max(m, c); } /** * Returns the biggest value among the provided values. * * @param a the first float value. * @param b the second float value. * @param c the third float value. * @return the biggest value among the provided values. */ public static float max(final float a, final float b, final float c) { return Math.max(Math.max(a, b), c); } /** * Returns the biggest value among the provided values. * * @param a the first double value. * @param b the second double value. * @param c the third double value. * @return the biggest value among the provided values. */ public static double max(final double a, final double b, final double c) { return Math.max(Math.max(a, b), c); } /** * Returns the biggest value among the provided values based on their natural ordering. Null values are considered to be minimum here. * * @param the type of the objects being compared, which must be comparable. * @param a the first object to compare. * @param b the second object to compare. * @param c the third object to compare. * @return the biggest value among the provided values. */ public static > T max(final T a, final T b, final T c) { return max(a, b, c, (Comparator) NULL_MIN_COMPARATOR); } /** * Returns the biggest value among the provided values according to the provided comparator. * * @param the type of the objects being compared. * @param a the first object to compare. * @param b the second object to compare. * @param c the third object to compare. * @param cmp the comparator to be used to compare the objects * @return the biggest value among the provided values. */ public static T max(final T a, final T b, final T c, final Comparator cmp) { return max(max(a, b, cmp), c, cmp); } /** * Returns the biggest char value in the specified array of char values. * * @param a the array of char values to be compared. * @return the biggest char value in the array. * @throws IllegalArgumentException if the specified array is {@code null} or empty. */ @SafeVarargs public static char max(final char... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return max(a, 0, a.length); } /** * Returns the biggest char value within the given range in the specified array of char values. * * @param a the array of char values to be compared. * @param fromIndex the index of the first element (inclusive) to be considered in the range. * @param toIndex the index of the last element (exclusive) to be considered in the range. * @return the biggest char value within the specified range of the array. * @throws IllegalArgumentException if the specified array or range is empty. */ public static char max(final char[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } char max = a[fromIndex]; for (int i = fromIndex + 1; i < toIndex; i++) { if (a[i] > max) { max = a[i]; } } return max; } /** * Returns the biggest byte value in the specified array of byte values. * * @param a the array of byte values to be compared. * @return the biggest byte value in the array. * @throws IllegalArgumentException if the specified array is {@code null} or empty. */ @SafeVarargs public static byte max(final byte... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return max(a, 0, a.length); } /** * Returns the biggest byte value within the given range in the specified array of byte values. * * @param a the array of byte values to be compared. * @param fromIndex the index of the first element (inclusive) to be considered in the range. * @param toIndex the index of the last element (exclusive) to be considered in the range. * @return the biggest byte value within the specified range of the array. * @throws IllegalArgumentException if the specified array or range is empty. */ public static byte max(final byte[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } byte max = a[fromIndex]; for (int i = fromIndex + 1; i < toIndex; i++) { if (a[i] > max) { max = a[i]; } } return max; } /** * Returns the biggest short value in the specified array of short values. * * @param a the array of short values to be compared. * @return the biggest short value in the array. * @throws IllegalArgumentException if the specified array is {@code null} or empty. */ @SafeVarargs public static short max(final short... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return max(a, 0, a.length); } /** * Returns the biggest short value within the given range in the specified array of short values. * * @param a the array of short values to be compared. * @param fromIndex the index of the first element (inclusive) to be considered in the range. * @param toIndex the index of the last element (exclusive) to be considered in the range. * @return the biggest short value within the specified range of the array. * @throws IllegalArgumentException if the specified array or range is empty. */ public static short max(final short[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } short max = a[fromIndex]; for (int i = fromIndex + 1; i < toIndex; i++) { if (a[i] > max) { max = a[i]; } } return max; } /** * Returns the biggest int value in the specified array of int values. * * @param a the array of int values to be compared. * @return the biggest int value in the array. * @throws IllegalArgumentException if the specified array is {@code null} or empty. */ @SafeVarargs public static int max(final int... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return max(a, 0, a.length); } /** * Returns the biggest int value within the given range in the specified array of int values. * * @param a the array of int values to be compared. * @param fromIndex the index of the first element (inclusive) to be considered in the range. * @param toIndex the index of the last element (exclusive) to be considered in the range. * @return the biggest int value within the specified range of the array. * @throws IllegalArgumentException if the specified array or range is empty. */ public static int max(final int[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } int max = a[fromIndex]; for (int i = fromIndex + 1; i < toIndex; i++) { if (a[i] > max) { max = a[i]; } } return max; } /** * Returns the biggest long value in the specified array of long values. * * @param a the array of long values to be compared. * @return the biggest long value in the array. * @throws IllegalArgumentException if the specified array is {@code null} or empty. */ @SafeVarargs public static long max(final long... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return max(a, 0, a.length); } /** * Returns the biggest long value within the given range in the specified array of long values. * * @param a the array of long values to be compared. * @param fromIndex the index of the first element (inclusive) to be considered in the range. * @param toIndex the index of the last element (exclusive) to be considered in the range. * @return the biggest long value within the specified range of the array. * @throws IllegalArgumentException if the specified array or range is empty. */ public static long max(final long[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } long max = a[fromIndex]; for (int i = fromIndex + 1; i < toIndex; i++) { if (a[i] > max) { max = a[i]; } } return max; } /** * Returns the biggest float value in the specified array of float values. * * @param a the array of float values to be compared. * @return the biggest float value in the array. * @throws IllegalArgumentException if the specified array is {@code null} or empty. * @see IEEE754rUtil#max(float[]) that handles NaN differently */ @SafeVarargs public static float max(final float... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return max(a, 0, a.length); } /** * Returns the biggest float value within the given range in the specified array of float values. * * @param a the array of float values to be compared. * @param fromIndex the index of the first element (inclusive) to be considered in the range. * @param toIndex the index of the last element (exclusive) to be considered in the range. * @return the biggest float value within the specified range of the array. * @throws IllegalArgumentException if the specified array or range is empty. * @see IEEE754rUtil#max(float[]) that handles NaN differently */ public static float max(final float[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } float max = a[fromIndex]; for (int i = fromIndex + 1; i < toIndex; i++) { max = Math.max(max, a[i]); if (Float.isNaN(max)) { return max; } } return max; } /** * Returns the biggest double value in the specified array of double values. * * @param a the array of double values to be compared. * @return the biggest double value in the array. * @throws IllegalArgumentException if the specified array is {@code null} or empty. * @see IEEE754rUtil#max(double[]) that handles NaN differently */ @SafeVarargs public static double max(final double... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return max(a, 0, a.length); } /** * Returns the biggest double value within the given range in the specified array of double values. * * @param a the array of double values to be compared. * @param fromIndex the index of the first element (inclusive) to be considered in the range. * @param toIndex the index of the last element (exclusive) to be considered in the range. * @return the biggest double value within the specified range of the array. * @throws IllegalArgumentException if the specified array or range is empty. * @see IEEE754rUtil#max(double[]) that handles NaN differently */ public static double max(final double[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } double max = a[fromIndex]; for (int i = fromIndex + 1; i < toIndex; i++) { max = Math.max(max, a[i]); if (Double.isNaN(max)) { return max; } } return max; } /** * Returns the biggest element in the specified array based on their natural ordering. Null values are considered to be minimum here. * * @param the type of the objects being compared, which must be comparable. * @param a the array of comparable objects to be compared. * @return the biggest element in the array. * @throws IllegalArgumentException if the specified array is {@code null} or empty. * @see Iterables#max(Comparable[]) */ public static > T max(final T[] a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return max(a, 0, a.length); } /** * Returns the biggest element within the given range in the specified array based on their natural ordering. Null values are considered to be minimum here. * * @param the type of the objects being compared, which must be comparable. * @param a the array of comparable objects to be compared. * @param fromIndex the index of the first element (inclusive) to be considered in the range. * @param toIndex the index of the last element (exclusive) to be considered in the range. * @return the biggest element within the specified range of the array. * @throws IllegalArgumentException if the specified array or range is empty. * @see Iterables#max(Comparable[]) */ public static > T max(final T[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException { return max(a, fromIndex, toIndex, (Comparator) NULL_MIN_COMPARATOR); } /** * Returns the biggest element in the specified array according to the provided comparator. * * @param the type of the objects being compared. * @param a the array of objects to be compared. * @param cmp the comparator to be used to compare the objects * @return the biggest element in the array. * @throws IllegalArgumentException if the specified array is {@code null} or empty. * @see Iterables#max(Object[], Comparator) */ public static T max(final T[] a, final Comparator cmp) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return max(a, 0, a.length, cmp); } /** * Returns the biggest element within the given range in the specified array according to the provided comparator. * * @param the type of the objects being compared. * @param a the array of objects to be compared. * @param fromIndex the index of the first element (inclusive) to be considered in the range. * @param toIndex the index of the last element (exclusive) to be considered in the range. * @param cmp the comparator to be used to compare the objects * @return the biggest element within the specified range of the array. * @throws IllegalArgumentException if the specified array or range is empty. * @see Iterables#max(Object[], Comparator) */ public static T max(final T[] a, final int fromIndex, final int toIndex, Comparator cmp) throws IndexOutOfBoundsException, IllegalArgumentException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } cmp = cmp == null ? (Comparator) NULL_MIN_COMPARATOR : cmp; T candidate = a[fromIndex]; for (int i = fromIndex + 1; i < toIndex; i++) { if (cmp.compare(a[i], candidate) > 0) { candidate = a[i]; } if (candidate == null && cmp == NULL_MAX_COMPARATOR) { // NOSONAR return null; } } return candidate; } /** * Returns the biggest element within the given range in the specified collection according to the provided comparator. * * @param the type of the objects being compared. * @param c the collection of objects to be compared. * @param fromIndex the index of the first element (inclusive) to be considered in the range. * @param toIndex the index of the last element (exclusive) to be considered in the range. * @return the biggest element within the specified range of the collection. * @throws IllegalArgumentException if the specified collection or range is empty. * @see Iterables#max(Iterable) */ public static > T max(final Collection c, final int fromIndex, final int toIndex) throws IllegalArgumentException { checkArgNotEmpty(c, "The specified collection can not be null or empty"); return max(c, fromIndex, toIndex, (Comparator) NULL_MIN_COMPARATOR); } /** * Returns the biggest element within the given range in the specified collection according to the provided comparator. * * @param the type of the objects being compared. * @param c the collection of objects to be compared. * @param fromIndex the index of the first element (inclusive) to be considered in the range. * @param toIndex the index of the last element (exclusive) to be considered in the range. * @param cmp the comparator to be used to compare the objects * @return the biggest element within the specified range of the collection. * @throws IllegalArgumentException if the specified collection or range is empty. * @see Iterables#max(Iterable, Comparator) */ public static T max(final Collection c, final int fromIndex, final int toIndex, Comparator cmp) throws IllegalArgumentException { checkFromToIndex(fromIndex, toIndex, size(c)); if (isEmpty(c) || toIndex - fromIndex < 1 || fromIndex >= c.size()) { throw new IllegalArgumentException("The size of collection can not be null or empty"); } cmp = cmp == null ? (Comparator) NULL_MIN_COMPARATOR : cmp; T candidate = null; T e = null; if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; candidate = list.get(fromIndex); for (int i = fromIndex + 1; i < toIndex; i++) { e = list.get(i); if (cmp.compare(e, candidate) > 0) { candidate = e; } if (candidate == null && cmp == NULL_MAX_COMPARATOR) { // NOSONAR return null; } } } else { final Iterator it = c.iterator(); for (int i = 0; i < toIndex; i++) { if (i < fromIndex) { it.next(); continue; } else if (i == fromIndex) { candidate = it.next(); } else { e = it.next(); if (cmp.compare(e, candidate) > 0) { candidate = e; } } if (candidate == null && cmp == NULL_MAX_COMPARATOR) { // NOSONAR return null; } } } return candidate; } /** * Returns the biggest element in the specified iterable based on their natural ordering. Null values are considered to be minimum here. * * @param the type of the objects being compared, which must be comparable. * @param c the iterable of comparable objects to be compared. * @return the biggest element in the iterable. * @throws IllegalArgumentException if the specified iterable is {@code null} or empty. * @see Iterables#max(Iterable) */ public static > T max(final Iterable c) throws IllegalArgumentException { return max(c, (Comparator) NULL_MIN_COMPARATOR); } /** * Returns the biggest element in the specified iterable according to the provided comparator. * * @param the type of the objects being compared. * @param c the iterable of objects to be compared. * @param cmp the comparator to be used to compare the objects * @return the biggest element in the iterable. * @throws IllegalArgumentException if the specified iterable is {@code null} or empty. * @see Iterables#max(Iterable, Comparator) */ public static T max(final Iterable c, final Comparator cmp) throws IllegalArgumentException { if (c instanceof Collection) { final Collection coll = (Collection) c; return max(coll, 0, coll.size(), cmp); } final Iterator iter = Iterables.iterateNonEmpty(c, "The specified Collection/Iterable/Iterator can not be null or empty"); //NOSONAR return max(iter, cmp); } /** * Returns the biggest element in the specified iterator based on their natural ordering. Null values are considered to be minimum here. * * @param the type of the objects being compared, which must be comparable. * @param iter the iterator of comparable objects to be compared. * @return the biggest element in the iterator. * @throws IllegalArgumentException if the specified iterator is {@code null} or empty. * @see Iterables#max(Iterator) */ public static > T max(final Iterator iter) throws IllegalArgumentException { return max(iter, (Comparator) NULL_MIN_COMPARATOR); } /** * Returns the biggest element in the specified iterator according to the provided comparator. * * @param the type of the objects being compared. * @param iter the iterator of objects to be compared. * @param cmp the comparator to be used to compare the objects * @return the biggest element in the iterator. * @throws IllegalArgumentException if the specified iterator is {@code null} or empty. * @see Iterables#max(Iterator, Comparator) */ public static T max(final Iterator iter, Comparator cmp) throws IllegalArgumentException { checkArgument(!isEmpty(iter), "The specified Collection/Iterable/Iterator can not be null or empty"); cmp = cmp == null ? (Comparator) NULL_MIN_COMPARATOR : cmp; T candidate = iter.next(); T e = null; while (iter.hasNext()) { e = iter.next(); if (cmp.compare(e, candidate) > 0) { candidate = e; } if (candidate == null && cmp == NULL_MAX_COMPARATOR) { // NOSONAR return null; } } return candidate; } /** * Returns a list containing the biggest elements in the specified array based on their natural ordering. Null values are considered to be minimum here. * * @param the type of elements in the input array, which must be comparable. * @param a the array to fetch the biggest elements. * @return a list containing the biggest elements in the array. If the array is {@code null} or empty, an empty list is returned. */ public static > List maxAll(final T[] a) { return maxAll(a, NULL_MIN_COMPARATOR); } /** * Returns a list containing all biggest elements in the specified array according to the provided comparator. * * @param the type of elements in the input array. * @param a the array to fetch the biggest elements from. * @param cmp the comparator to be used to compare the elements * @return a list containing all biggest elements in the array. If the array is {@code null} or empty, an empty list is returned. */ public static List maxAll(final T[] a, Comparator cmp) { if (isEmpty(a)) { return new ArrayList<>(); } cmp = cmp == null ? (Comparator) NULL_MIN_COMPARATOR : cmp; final List result = new ArrayList<>(); T candidate = a[0]; int cp = 0; result.add(candidate); for (int i = 1, len = a.length; i < len; i++) { cp = cmp.compare(a[i], candidate); if (cp == 0) { result.add(a[i]); } else if (cp > 0) { result.clear(); result.add(a[i]); candidate = a[i]; } } return result; } /** * Returns a list containing the biggest elements in the specified iterable based on their natural ordering. Null values are considered to be minimum here. * * @param the type of elements in the input iterable, which must be comparable. * @param c the iterable to fetch the biggest elements. * @return a list containing the biggest elements in the iterable. If the iterable is {@code null} or empty, an empty list is returned. */ public static > List maxAll(final Iterable c) { return maxAll(c, NULL_MIN_COMPARATOR); } /** * Returns a list containing all biggest elements in the specified iterable according to the provided comparator. * * @param the type of elements in the input iterable. * @param c the iterable to fetch the biggest elements from. * @param cmp the comparator to be used to compare the elements * @return a list containing all biggest elements in the iterable. If the iterable is {@code null} or empty, an empty list is returned. */ public static List maxAll(final Iterable c, final Comparator cmp) { if (isEmptyCollection(c)) { return new ArrayList<>(); } return maxAll(c.iterator(), cmp); } /** * Returns a list containing the biggest elements in the specified iterator based on their natural ordering. Null values are considered to be minimum here. * * @param the type of elements in the input iterator, which must be comparable. * @param iter the iterator to fetch the biggest elements. * @return a list containing the biggest elements in the iterator. If the iterator is {@code null} or empty, an empty list is returned. */ public static > List maxAll(final Iterator iter) { return maxAll(iter, NULL_MIN_COMPARATOR); } /** * Returns a list containing all biggest elements in the specified iterator according to the provided comparator. * * @param the type of elements in the input iterator. * @param iter the iterator to fetch the biggest elements from. * @param cmp the comparator to be used to compare the elements * @return a list containing all biggest elements in the iterator. If the iterator is {@code null} or empty, an empty list is returned. */ public static List maxAll(final Iterator iter, Comparator cmp) { cmp = cmp == null ? (Comparator) NULL_MIN_COMPARATOR : cmp; final List result = new ArrayList<>(); T candidate = iter.next(); T next = null; int cp = 0; result.add(candidate); while (iter.hasNext()) { next = iter.next(); cp = cmp.compare(next, candidate); if (cp == 0) { result.add(next); } else if (cp > 0) { result.clear(); result.add(next); candidate = next; } } return result; } /** * Returns the maximum value extracted from the specified array or a default value if the array is {@code null} or empty. Null values are considered to be minimum here. * * @param the type of elements in the input array. * @param the type of the extracted value, which must be comparable. * @param a the array to extract the maximum value from. * @param valueExtractor the function to extract values from the array elements for comparison. * @param defaultValue the default value to return if the array is {@code null} or empty. * @return the maximum extracted value or the default value if the array is {@code null} or empty. */ @Beta public static > R maxOrDefaultIfEmpty(final T[] a, final Function valueExtractor, final R defaultValue) { if (isEmpty(a)) { return defaultValue; } R candidate = valueExtractor.apply(a[0]); R next = null; for (int i = 1, len = a.length; i < len; i++) { next = valueExtractor.apply(a[i]); if (candidate == null || (next != null && (next.compareTo(candidate) > 0))) { candidate = next; } } return candidate; } /** * Returns the maximum value extracted from the specified iterable or a default value if the iterable is {@code null} or empty. Null values are considered to be minimum here. * * @param the type of elements in the input iterable. * @param the type of the extracted value, which must be comparable. * @param c the iterable to extract the maximum value from. * @param valueExtractor the function to extract values from the iterable elements for comparison. * @param defaultValue the default value to return if the iterable is {@code null} or empty. * @return the maximum extracted value or the default value if the iterable is {@code null} or empty. */ public static > R maxOrDefaultIfEmpty(final Iterable c, final Function valueExtractor, final R defaultValue) { if (isEmptyCollection(c)) { return defaultValue; } return maxOrDefaultIfEmpty(c.iterator(), valueExtractor, defaultValue); } /** * Returns the maximum value extracted from the specified iterator or a default value if the iterator is {@code null} or empty. Null values are considered to be minimum here. * * @param the type of elements in the input iterator. * @param the type of the extracted value, which must be comparable. * @param iter the iterator to extract the maximum value from. * @param valueExtractor the function to extract values from the iterator elements for comparison. * @param defaultValue the default value to return if the iterator is {@code null} or empty. * @return the maximum extracted value or the default value if the iterator is {@code null} or empty. */ public static > R maxOrDefaultIfEmpty(final Iterator iter, final Function valueExtractor, final R defaultValue) { if (iter == null || !iter.hasNext()) { return defaultValue; } R candidate = valueExtractor.apply(iter.next()); R next = null; while (iter.hasNext()) { next = valueExtractor.apply(iter.next()); if (candidate == null || (next != null && (next.compareTo(candidate) > 0))) { candidate = next; } } return candidate; } /** * Returns the maximum integer value extracted from the array or a default value if the array is {@code null} or empty. * * @param the type of elements in the input array. * @param a the array to extract the maximum integer from. * @param valueExtractor the function to extract integer values from the array elements. * @param defaultValue the default value to return if the array is {@code null} or empty. * @return the maximum extracted integer value or the default value if the array is {@code null} or empty. */ @Beta public static int maxIntOrDefaultIfEmpty(final T[] a, final ToIntFunction valueExtractor, final int defaultValue) { if (isEmpty(a)) { return defaultValue; } int candidate = valueExtractor.applyAsInt(a[0]); int next = 0; for (int i = 1, len = a.length; i < len; i++) { next = valueExtractor.applyAsInt(a[i]); if (next > candidate) { candidate = next; } } return candidate; } /** * Returns the maximum integer value extracted from the iterable or a default value if the iterable is {@code null} or empty. * * @param the type of elements in the input iterable. * @param c the iterable to extract the maximum integer from. * @param valueExtractor the function to extract integer values from the iterable elements. * @param defaultValue the default value to return if the iterable is {@code null} or empty. * @return the maximum extracted integer value or the default value if the iterable is {@code null} or empty. */ @Beta public static int maxIntOrDefaultIfEmpty(final Iterable c, final ToIntFunction valueExtractor, final int defaultValue) { if (isEmptyCollection(c)) { return defaultValue; } return maxIntOrDefaultIfEmpty(c.iterator(), valueExtractor, defaultValue); } /** * Returns the maximum integer value extracted from the iterator or a default value if the iterator is {@code null} or empty. * * @param the type of elements in the input iterator. * @param iter the iterator to extract the maximum integer from. * @param valueExtractor the function to extract integer values from the iterator elements. * @param defaultValue the default value to return if the iterator is {@code null} or empty. * @return the maximum extracted integer value or the default value if the iterator is {@code null} or empty. */ @Beta public static int maxIntOrDefaultIfEmpty(final Iterator iter, final ToIntFunction valueExtractor, final int defaultValue) { if (iter == null || !iter.hasNext()) { return defaultValue; } int candidate = valueExtractor.applyAsInt(iter.next()); int next = 0; while (iter.hasNext()) { next = valueExtractor.applyAsInt(iter.next()); if (next > candidate) { candidate = next; } } return candidate; } /** * Returns the maximum long value extracted from the array or a default value if the array is {@code null} or empty. * * @param the type of elements in the input array. * @param a the array to extract the maximum long from. * @param valueExtractor the function to extract long values from the array elements. * @param defaultValue the default value to return if the array is {@code null} or empty. * @return the maximum extracted long value or the default value if the array is {@code null} or empty. */ @Beta public static long maxLongOrDefaultIfEmpty(final T[] a, final ToLongFunction valueExtractor, final long defaultValue) { if (isEmpty(a)) { return defaultValue; } long candidate = valueExtractor.applyAsLong(a[0]); long next = 0; for (int i = 1, len = a.length; i < len; i++) { next = valueExtractor.applyAsLong(a[i]); if (next > candidate) { candidate = next; } } return candidate; } /** * Returns the maximum long value extracted from the iterable or a default value if the iterable is {@code null} or empty. * * @param the type of elements in the input iterable. * @param c the iterable to extract the maximum long from. * @param valueExtractor the function to extract long values from the iterable elements. * @param defaultValue the default value to return if the iterable is {@code null} or empty. * @return the maximum extracted long value or the default value if the iterable is {@code null} or empty. */ @Beta public static long maxLongOrDefaultIfEmpty(final Iterable c, final ToLongFunction valueExtractor, final long defaultValue) { if (isEmptyCollection(c)) { return defaultValue; } return maxLongOrDefaultIfEmpty(c.iterator(), valueExtractor, defaultValue); } /** * Returns the maximum long value extracted from the iterator or a default value if the iterator is {@code null} or empty. * * @param the type of elements in the input iterator. * @param iter the iterator to extract the maximum long from. * @param valueExtractor the function to extract long values from the iterator elements. * @param defaultValue the default value to return if the iterator is {@code null} or empty. * @return the maximum extracted long value or the default value if the iterator is {@code null} or empty. */ @Beta public static long maxLongOrDefaultIfEmpty(final Iterator iter, final ToLongFunction valueExtractor, final long defaultValue) { if (iter == null || !iter.hasNext()) { return defaultValue; } long candidate = valueExtractor.applyAsLong(iter.next()); long next = 0; while (iter.hasNext()) { next = valueExtractor.applyAsLong(iter.next()); if (next > candidate) { candidate = next; } } return candidate; } /** * Returns the maximum double value extracted from the array or a default value if the array is {@code null} or empty. * * @param the type of elements in the input array. * @param a the array to extract the maximum double from. * @param valueExtractor the function to extract double values from the array elements. * @param defaultValue the default value to return if the array is {@code null} or empty. * @return the maximum extracted double value or the default value if the array is {@code null} or empty. */ @Beta public static double maxDoubleOrDefaultIfEmpty(final T[] a, final ToDoubleFunction valueExtractor, final double defaultValue) { if (isEmpty(a)) { return defaultValue; } double candidate = valueExtractor.applyAsDouble(a[0]); double next = 0; for (int i = 1, len = a.length; i < len; i++) { next = valueExtractor.applyAsDouble(a[i]); if (compare(next, candidate) > 0) { candidate = next; } } return candidate; } /** * Returns the maximum double value extracted from the iterable or a default value if the iterable is {@code null} or empty. * * @param the type of elements in the input iterable. * @param c the iterable to extract the maximum double from. * @param valueExtractor the function to extract double values from the iterable elements. * @param defaultValue the default value to return if the iterable is {@code null} or empty. * @return the maximum extracted double value or the default value if the iterable is {@code null} or empty. */ @Beta public static double maxDoubleOrDefaultIfEmpty(final Iterable c, final ToDoubleFunction valueExtractor, final double defaultValue) { if (isEmptyCollection(c)) { return defaultValue; } return maxDoubleOrDefaultIfEmpty(c.iterator(), valueExtractor, defaultValue); } /** * Returns the maximum double value extracted from the iterator or a default value if the iterator is {@code null} or empty. * * @param the type of elements in the input iterator. * @param iter the iterator to extract the maximum double from. * @param valueExtractor the function to extract double values from the iterator elements. * @param defaultValue the default value to return if the iterator is {@code null} or empty. * @return the maximum extracted double value or the default value if the iterator is {@code null} or empty. */ @Beta public static double maxDoubleOrDefaultIfEmpty(final Iterator iter, final ToDoubleFunction valueExtractor, final double defaultValue) { if (iter == null || !iter.hasNext()) { return defaultValue; } double candidate = valueExtractor.applyAsDouble(iter.next()); double next = 0; while (iter.hasNext()) { next = valueExtractor.applyAsDouble(iter.next()); if (compare(next, candidate) > 0) { candidate = next; } } return candidate; } /** * Returns the median value of the three specified char values. * * @param a the first char value. * @param b the second char value. * @param c the third char value. * @return the median of the three specified char values. * @see #median(int[]) */ public static char median(final char a, final char b, final char c) { if ((a >= b && a <= c) || (a >= c && a <= b)) { return a; } else if ((b >= a && b <= c) || (b >= c && b <= a)) { return b; } else { return c; } } /** * Returns the median value of the three specified byte values. * * @param a the first byte value. * @param b the second byte value. * @param c the third byte value. * @return the median of the three specified byte values. * @see #median(int[]) */ public static byte median(final byte a, final byte b, final byte c) { if ((a >= b && a <= c) || (a >= c && a <= b)) { return a; } else if ((b >= a && b <= c) || (b >= c && b <= a)) { return b; } else { return c; } } /** * Returns the median value of the three specified short values. * * @param a the first short value. * @param b the second short value. * @param c the third short value. * @return the median of the three specified short values. * @see #median(int[]) */ public static short median(final short a, final short b, final short c) { if ((a >= b && a <= c) || (a >= c && a <= b)) { return a; } else if ((b >= a && b <= c) || (b >= c && b <= a)) { return b; } else { return c; } } /** * Returns the median value of the three specified int values. * * @param a the first int value. * @param b the second int value. * @param c the third int value. * @return the median of the three specified int values. * @see #median(int[]) */ public static int median(final int a, final int b, final int c) { if ((a >= b && a <= c) || (a >= c && a <= b)) { return a; } else if ((b >= a && b <= c) || (b >= c && b <= a)) { return b; } else { return c; } } /** * Returns the median value of the three specified long values. * * @param a the first long value. * @param b the second long value. * @param c the third long value. * @return the median of the three specified long values. * @see #median(int[]) */ public static long median(final long a, final long b, final long c) { if ((a >= b && a <= c) || (a >= c && a <= b)) { return a; } else if ((b >= a && b <= c) || (b >= c && b <= a)) { return b; } else { return c; } } /** * Returns the median value of the three specified float values. * * @param a the first float value. * @param b the second float value. * @param c the third float value. * @return the median of the three specified float values. * @see #median(int[]) */ public static float median(final float a, final float b, final float c) { final int ab = Float.compare(a, b); final int ac = Float.compare(a, c); int bc = 0; if ((ab >= 0 && ac <= 0) || (ac >= 0 && ab <= 0)) { return a; } else if ((((bc = Float.compare(b, c)) <= 0) && ab <= 0) || (bc >= 0 && ab >= 0)) { return b; } else { return c; } } /** * Returns the median value of the three specified double values. * * @param a the first double value. * @param b the second double value. * @param c the third double value. * @return the median of the three specified double values. * @see #median(int[]) */ public static double median(final double a, final double b, final double c) { final int ab = Double.compare(a, b); final int ac = Double.compare(a, c); int bc = 0; if ((ab >= 0 && ac <= 0) || (ac >= 0 && ab <= 0)) { return a; } else if ((((bc = Double.compare(b, c)) <= 0) && ab <= 0) || (bc >= 0 && ab >= 0)) { return b; } else { return c; } } /** * Returns the median of the provided values based on their natural ordering. Null values are considered to be minimum here. * * @param the type of the objects being compared, which must be comparable. * @param a the first value. * @param b the second value. * @param c the third value. * @return the median of the three specified values. * @see #median(int[]) */ public static > T median(final T a, final T b, final T c) { return (T) median(a, b, c, NATURAL_COMPARATOR); } /** * Returns the median of the provided values according to the provided comparator. * * @param the type of the objects being compared. * @param a the first value. * @param b the second value. * @param c the third value. * @param cmp the comparator to be used to compare the objects * @return the median of the three specified values. * @see #median(int[]) */ public static T median(final T a, final T b, final T c, Comparator cmp) { cmp = checkComparator(cmp); final int ab = cmp.compare(a, b); final int ac = cmp.compare(a, c); int bc = 0; if ((ab >= 0 && ac <= 0) || (ac >= 0 && ab <= 0)) { return a; } else if ((((bc = cmp.compare(b, c)) <= 0) && ab <= 0) || (bc >= 0 && ab >= 0)) { return b; } else { return c; } } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest value in the specified array. * * @param a the array of values to find the median of * @return the median in the specified array * @throws IllegalArgumentException if the array is {@code null} or empty * @see #median(int[]) */ @SafeVarargs public static char median(final char... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return median(a, 0, a.length); } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest value within the given range in the specified array * * @param a the array of values to find the median of * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @return the median within the specified range in the input array * @throws IllegalArgumentException if the specified array or range is {@code null} or empty * @throws IndexOutOfBoundsException if the range is out of the array bounds * @see #median(int[]) */ public static char median(final char[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } checkFromToIndex(fromIndex, toIndex, a.length); final int len = toIndex - fromIndex; if (len == 1) { return a[fromIndex]; } else if (len == 2) { return min(a[fromIndex], a[fromIndex + 1]); } else if (len == 3) { return median(a[fromIndex], a[fromIndex + 1], a[fromIndex + 2]); } else { return kthLargest(a, fromIndex, toIndex, len / 2 + 1); } } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest value in the specified array. * * @param a the array of values to find the median of * @return the median in the specified array * @throws IllegalArgumentException if the array is {@code null} or empty * @see #median(int[]) */ @SafeVarargs public static byte median(final byte... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return median(a, 0, a.length); } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest value within the given range in the specified array * * @param a the array of values to find the median of * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @return the median within the specified range in the input array * @throws IllegalArgumentException if the specified array or range is {@code null} or empty * @throws IndexOutOfBoundsException if the range is out of the array bounds * @see #median(int[]) */ public static byte median(final byte[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } checkFromToIndex(fromIndex, toIndex, a.length); final int len = toIndex - fromIndex; if (len == 1) { return a[fromIndex]; } else if (len == 2) { return min(a[fromIndex], a[fromIndex + 1]); } else if (len == 3) { return median(a[fromIndex], a[fromIndex + 1], a[fromIndex + 2]); } else { return kthLargest(a, fromIndex, toIndex, len / 2 + 1); } } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest value in the specified array. * * @param a the array of values to find the median of * @return the median in the specified array * @throws IllegalArgumentException if the array is {@code null} or empty * @see #median(int[]) */ @SafeVarargs public static short median(final short... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return median(a, 0, a.length); } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest value within the given range in the specified array * * @param a the array of values to find the median of * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @return the median within the specified range in the input array * @throws IllegalArgumentException if the specified array or range is {@code null} or empty * @throws IndexOutOfBoundsException if the range is out of the array bounds * @see #median(int[]) */ public static short median(final short[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } checkFromToIndex(fromIndex, toIndex, a.length); final int len = toIndex - fromIndex; if (len == 1) { return a[fromIndex]; } else if (len == 2) { return min(a[fromIndex], a[fromIndex + 1]); } else if (len == 3) { return median(a[fromIndex], a[fromIndex + 1], a[fromIndex + 2]); } else { return kthLargest(a, fromIndex, toIndex, len / 2 + 1); } } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest value in the specified array. * *
     * 
     * N.media([1]) => 1
     * N.media([1, 2]) => 1
     * N.media([2, 1]) => 1
     * N.media([1, 2, 3]) => 2
     * N.media([1, 3, 2]) => 2
     * N.media([1, 2, 3, 4]) => 2
     * N.media([1, 3, 2, 4]) => 2
     * 
     * 
* * @param a the array of values to find the median of * @return the median in the specified array * @throws IllegalArgumentException if the array is {@code null} or empty */ @SafeVarargs public static int median(final int... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return median(a, 0, a.length); } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest value within the given range in the specified array * * @param a the array of values to find the median of * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @return the median within the specified range in the input array * @throws IllegalArgumentException if the specified array or range is {@code null} or empty * @throws IndexOutOfBoundsException if the range is out of the array bounds * @see #median(int[]) */ public static int median(final int[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } checkFromToIndex(fromIndex, toIndex, a.length); final int len = toIndex - fromIndex; if (len == 1) { return a[fromIndex]; } else if (len == 2) { return min(a[fromIndex], a[fromIndex + 1]); } else if (len == 3) { return median(a[fromIndex], a[fromIndex + 1], a[fromIndex + 2]); } else { return kthLargest(a, fromIndex, toIndex, len / 2 + 1); } } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest value in the specified array. * * @param a the array of values to find the median of * @return the median in the specified array * @throws IllegalArgumentException if the array is {@code null} or empty * @see #median(int[]) */ @SafeVarargs public static long median(final long... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return median(a, 0, a.length); } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest value within the given range in the specified array * * @param a the array of values to find the median of * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @return the median within the specified range in the input array * @throws IllegalArgumentException if the specified array or range is {@code null} or empty * @throws IndexOutOfBoundsException if the range is out of the array bounds * @see #median(int[]) */ public static long median(final long[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } checkFromToIndex(fromIndex, toIndex, a.length); final int len = toIndex - fromIndex; if (len == 1) { return a[fromIndex]; } else if (len == 2) { return min(a[fromIndex], a[fromIndex + 1]); } else if (len == 3) { return median(a[fromIndex], a[fromIndex + 1], a[fromIndex + 2]); } else { return kthLargest(a, fromIndex, toIndex, len / 2 + 1); } } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest value in the specified array. * * @param a the array of values to find the median of * @return the median in the specified array * @throws IllegalArgumentException if the array is {@code null} or empty * @see #median(int[]) */ @SafeVarargs public static float median(final float... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return median(a, 0, a.length); } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest value within the given range in the specified array * * @param a the array of values to find the median of * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @return the median within the specified range in the input array * @throws IllegalArgumentException if the specified array or range is {@code null} or empty * @throws IndexOutOfBoundsException if the range is out of the array bounds * @see #median(int[]) */ public static float median(final float[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } checkFromToIndex(fromIndex, toIndex, a.length); final int len = toIndex - fromIndex; if (len == 1) { return a[fromIndex]; } else if (len == 2) { return min(a[fromIndex], a[fromIndex + 1]); } else if (len == 3) { return median(a[fromIndex], a[fromIndex + 1], a[fromIndex + 2]); } else { return kthLargest(a, fromIndex, toIndex, len / 2 + 1); } } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest value in the specified array. * * @param a the array of values to find the median of * @return the median in the specified array * @throws IllegalArgumentException if the array is {@code null} or empty * @see #median(int[]) */ @SafeVarargs public static double median(final double... a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return median(a, 0, a.length); } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest value within the given range in the specified array * * @param a the array of values to find the median of * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @return the median within the specified range in the input array * @throws IllegalArgumentException if the specified array or range is {@code null} or empty * @throws IndexOutOfBoundsException if the range is out of the array bounds * @see #median(int[]) */ public static double median(final double[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } checkFromToIndex(fromIndex, toIndex, a.length); final int len = toIndex - fromIndex; if (len == 1) { return a[fromIndex]; } else if (len == 2) { return min(a[fromIndex], a[fromIndex + 1]); } else if (len == 3) { return median(a[fromIndex], a[fromIndex + 1], a[fromIndex + 2]); } else { return kthLargest(a, fromIndex, toIndex, len / 2 + 1); } } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest value in the specified array. * * @param a the array of values to find the median of * @return the median in the specified array * @throws IllegalArgumentException if the array is {@code null} or empty * @see #median(int[]) */ public static > T median(final T[] a) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return median(a, 0, a.length); } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest value within the given range in the specified array * * @param a the array of values to find the median of * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @return the median within the specified range in the input array * @throws IllegalArgumentException if the specified array or range is {@code null} or empty * @throws IndexOutOfBoundsException if the range is out of the array bounds * @see #median(int[]) */ public static > T median(final T[] a, final int fromIndex, final int toIndex) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } return (T) median(a, fromIndex, toIndex, NATURAL_COMPARATOR); } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest element in the specified array according to the provided comparator. * * @param the type of elements in the input array * @param a the array of values to find the median of * @param cmp the comparator to determine the order of the values * @return the median in the specified array * @throws IllegalArgumentException if the array is {@code null} or empty * @see #median(int[]) * @see Iterables#median(Collection, Comparator) * @see Median#of(Comparable[], int, int) * @see Median#of(Object[], int, int, Comparator) */ public static T median(final T[] a, final Comparator cmp) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return median(a, 0, a.length, cmp); } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest element within the specified range in the input array according to the provided comparator. * * @param the type of elements in the input array * @param a the array of values to find the median of * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @param cmp the comparator to determine the order of the values * @return the median within the specified range in the input array * @throws IllegalArgumentException if the specified array or range is {@code null} or empty * @throws IndexOutOfBoundsException if the range is out of the array bounds * @see #median(int[]) * @see Iterables#median(Collection, Comparator) * @see Median#of(Comparable[], int, int) * @see Median#of(Object[], int, int, Comparator) */ public static T median(final T[] a, final int fromIndex, final int toIndex, Comparator cmp) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } checkFromToIndex(fromIndex, toIndex, a.length); cmp = checkComparator(cmp); final int len = toIndex - fromIndex; return kthLargest(a, fromIndex, toIndex, len / 2 + 1, cmp); } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest element in the specified collection according to the provided comparator. * * @param the type of elements in the input collection * @param c the collection of values to find the median of * @return the median in the specified collection * @throws IllegalArgumentException if the collection is {@code null} or empty * @see #median(int[]) * @see Iterables#median(Collection, Comparator) * @see Median#of(Comparable[], int, int) * @see Median#of(Object[], int, int, Comparator) */ public static > T median(final Collection c) throws IllegalArgumentException { checkArgNotEmpty(c, "The specified collection can not be null or empty"); return median(c, 0, c.size()); } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest element within the specified range in the input collection according to the provided comparator. * * @param the type of elements in the input collection * @param c the collection of values to find the median of * @param fromIndex The start index (inclusive) of the range to consider in the collection * @param toIndex the end index (exclusive) of the range to consider in the collection * @return the median within the specified range in the input collection * @throws IllegalArgumentException if the specified collection or range is {@code null} or empty * @throws IndexOutOfBoundsException if the range is out of the collection bounds * @see #median(int[]) * @see Iterables#median(Collection, Comparator) * @see Median#of(Comparable[], int, int) * @see Median#of(Object[], int, int, Comparator) */ public static > T median(final Collection c, final int fromIndex, final int toIndex) throws IllegalArgumentException, IndexOutOfBoundsException { return (T) median(c, fromIndex, toIndex, NATURAL_COMPARATOR); } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest element in the specified collection according to the provided comparator. * * @param the type of elements in the input collection * @param c the collection of values to find the median of * @param cmp the comparator to determine the order of the values * @return the median in the specified collection * @throws IllegalArgumentException if the collection is {@code null} or empty * @see #median(int[]) * @see Iterables#median(Collection, Comparator) * @see Median#of(Comparable[], int, int) * @see Median#of(Object[], int, int, Comparator) */ public static T median(final Collection c, final Comparator cmp) throws IndexOutOfBoundsException, IllegalArgumentException { checkArgNotEmpty(c, "The specified collection can not be null or empty"); return median(c, 0, c.size(), cmp); } /** * Returns the {@code (sizeOfRange / 2 + 1)} largest element within the specified range in the input collection according to the provided comparator. * * @param the type of elements in the input collection * @param c the collection of values to find the median of * @param fromIndex The start index (inclusive) of the range to consider in the collection * @param toIndex the end index (exclusive) of the range to consider in the collection * @param cmp the comparator to determine the order of the values * @return the median within the specified range in the input collection * @throws IllegalArgumentException if the specified collection or range is {@code null} or empty * @throws IndexOutOfBoundsException if the range is out of the collection bounds * @see #median(int[]) * @see Iterables#median(Collection, Comparator) * @see Median#of(Comparable[], int, int) * @see Median#of(Object[], int, int, Comparator */ public static T median(final Collection c, final int fromIndex, final int toIndex, Comparator cmp) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(c) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The length of collection can not be null or empty"); //NOSONAR } checkFromToIndex(fromIndex, toIndex, c.size()); cmp = checkComparator(cmp); final int len = toIndex - fromIndex; return kthLargest(c, fromIndex, toIndex, len / 2 + 1, cmp); } /** * Returns the k-th largest element in the specified array. * * @param a the array to find the k-th largest element in * @param k the position (1-based) of the largest element to find * @return the k-th largest element in the array * @throws IllegalArgumentException if the specified array/range is {@code null} or empty, its length is less than k * @see #kthLargest(int[], int) */ public static char kthLargest(final char[] a, final int k) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return kthLargest(a, 0, a.length, k); } /** * Returns the k-th largest element within the specified range in the input array. * * @param a the array to find the k-th largest element in * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @param k the position (1-based) of the largest element to find * @return the k-th largest element within the specified range in the input array * @throws IllegalArgumentException if the specified array/range is {@code null} or empty, its length is less than k * @throws IndexOutOfBoundsException if the range is out of the array bounds * @see #kthLargest(int[], int) */ public static char kthLargest(final char[] a, final int fromIndex, final int toIndex, int k) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } checkFromToIndex(fromIndex, toIndex, len(a)); checkArgument(k > 0 && k <= toIndex - fromIndex, "'k' (%s) is out of range %s", k, toIndex - fromIndex); //NOSONAR final int len = toIndex - fromIndex; if (k == 1) { return max(a, fromIndex, toIndex); } else if (k == len) { return min(a, fromIndex, toIndex); } Queue queue = null; if (k <= len / 2) { queue = new PriorityQueue<>(k); for (int i = fromIndex; i < toIndex; i++) { if (queue.size() < k) { queue.add(a[i]); } else { if (a[i] > queue.peek()) { queue.remove(); queue.add(a[i]); } } } } else { k = len - k + 1; queue = new PriorityQueue<>(k, Comparator.reverseOrder()); for (int i = fromIndex; i < toIndex; i++) { if (queue.size() < k) { queue.add(a[i]); } else { //noinspection DataFlowIssue if (a[i] < queue.peek()) { queue.remove(); queue.add(a[i]); } } } } //noinspection DataFlowIssue return queue.peek(); } /** * Returns the k-th largest element in the specified array. * * @param a the array to find the k-th largest element in * @param k the position (1-based) of the largest element to find * @return the k-th largest element in the array * @throws IllegalArgumentException if the specified array/range is {@code null} or empty, its length is less than k * @see #kthLargest(int[], int) */ public static byte kthLargest(final byte[] a, final int k) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return kthLargest(a, 0, a.length, k); } /** * Returns the k-th largest element within the specified range in the input array. * * @param a the array to find the k-th largest element in * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @param k the position (1-based) of the largest element to find * @return the k-th largest element within the specified range in the input array * @throws IllegalArgumentException if the specified array/range is {@code null} or empty, its length is less than k * @throws IndexOutOfBoundsException if the range is out of the array bounds * @see #kthLargest(int[], int) */ public static byte kthLargest(final byte[] a, final int fromIndex, final int toIndex, int k) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } checkFromToIndex(fromIndex, toIndex, len(a)); checkArgument(k > 0 && k <= toIndex - fromIndex, "'k' (%s) is out of range %s", k, toIndex - fromIndex); final int len = toIndex - fromIndex; if (k == 1) { return max(a, fromIndex, toIndex); } else if (k == len) { return min(a, fromIndex, toIndex); } Queue queue = null; if (k <= len / 2) { queue = new PriorityQueue<>(k); for (int i = fromIndex; i < toIndex; i++) { if (queue.size() < k) { queue.add(a[i]); } else { if (a[i] > queue.peek()) { queue.remove(); queue.add(a[i]); } } } } else { k = len - k + 1; queue = new PriorityQueue<>(k, Comparator.reverseOrder()); for (int i = fromIndex; i < toIndex; i++) { if (queue.size() < k) { queue.add(a[i]); } else { //noinspection DataFlowIssue if (a[i] < queue.peek()) { queue.remove(); queue.add(a[i]); } } } } //noinspection DataFlowIssue return queue.peek(); } /** * Returns the k-th largest element in the specified array. * * @param a the array to find the k-th largest element in * @param k the position (1-based) of the largest element to find * @return the k-th largest element in the array * @throws IllegalArgumentException if the specified array/range is {@code null} or empty, its length is less than k * @see #kthLargest(int[], int) */ public static short kthLargest(final short[] a, final int k) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return kthLargest(a, 0, a.length, k); } /** * Returns the k-th largest element within the specified range in the input array. * * @param a the array to find the k-th largest element in * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @param k the position (1-based) of the largest element to find * @return the k-th largest element within the specified range in the input array * @throws IllegalArgumentException if the specified array/range is {@code null} or empty, its length is less than k * @throws IndexOutOfBoundsException if the range is out of the array bounds * @see #kthLargest(int[], int) */ public static short kthLargest(final short[] a, final int fromIndex, final int toIndex, int k) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } checkFromToIndex(fromIndex, toIndex, len(a)); checkArgument(k > 0 && k <= toIndex - fromIndex, "'k' (%s) is out of range %s", k, toIndex - fromIndex); final int len = toIndex - fromIndex; if (k == 1) { return max(a, fromIndex, toIndex); } else if (k == len) { return min(a, fromIndex, toIndex); } Queue queue = null; if (k <= len / 2) { queue = new PriorityQueue<>(k); for (int i = fromIndex; i < toIndex; i++) { if (queue.size() < k) { queue.add(a[i]); } else { if (a[i] > queue.peek()) { queue.remove(); queue.add(a[i]); } } } } else { k = len - k + 1; queue = new PriorityQueue<>(k, Comparator.reverseOrder()); for (int i = fromIndex; i < toIndex; i++) { if (queue.size() < k) { queue.add(a[i]); } else { //noinspection DataFlowIssue if (a[i] < queue.peek()) { queue.remove(); queue.add(a[i]); } } } } //noinspection DataFlowIssue return queue.peek(); } /** * Returns the k-th largest element in the specified array. * * @param a the array to find the k-th largest element in * @param k the position (1-based) of the largest element to find * @return the k-th largest element in the array * @throws IllegalArgumentException if the specified array/range is {@code null} or empty, its length is less than k * @see #kthLargest(int[], int) */ public static int kthLargest(final int[] a, final int k) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return kthLargest(a, 0, a.length, k); } /** * Returns the k-th largest element within the specified range in the input array. * * @param a the array to find the k-th largest element in * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @param k the position (1-based) of the largest element to find * @return the k-th largest element within the specified range in the input array * @throws IllegalArgumentException if the specified array/range is {@code null} or empty, its length is less than k * @throws IndexOutOfBoundsException if the range is out of the array bounds * @see #kthLargest(int[], int) */ public static int kthLargest(final int[] a, final int fromIndex, final int toIndex, int k) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } checkFromToIndex(fromIndex, toIndex, len(a)); checkArgument(k > 0 && k <= toIndex - fromIndex, "'k' (%s) is out of range %s", k, toIndex - fromIndex); final int len = toIndex - fromIndex; if (k == 1) { return max(a, fromIndex, toIndex); } else if (k == len) { return min(a, fromIndex, toIndex); } Queue queue = null; if (k <= len / 2) { queue = new PriorityQueue<>(k); for (int i = fromIndex; i < toIndex; i++) { if (queue.size() < k) { queue.add(a[i]); } else { if (a[i] > queue.peek()) { queue.remove(); queue.add(a[i]); } } } } else { k = len - k + 1; queue = new PriorityQueue<>(k, Comparator.reverseOrder()); for (int i = fromIndex; i < toIndex; i++) { if (queue.size() < k) { queue.add(a[i]); } else { //noinspection DataFlowIssue if (a[i] < queue.peek()) { queue.remove(); queue.add(a[i]); } } } } //noinspection DataFlowIssue return queue.peek(); } /** * Returns the k-th largest element in the specified array. * * @param a the array to find the k-th largest element in * @param k the position (1-based) of the largest element to find * @return the k-th largest element in the array * @throws IllegalArgumentException if the specified array/range is {@code null} or empty, its length is less than k * @see #kthLargest(int[], int) */ public static long kthLargest(final long[] a, final int k) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return kthLargest(a, 0, a.length, k); } /** * Returns the k-th largest element within the specified range in the input array. * * @param a the array to find the k-th largest element in * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @param k the position (1-based) of the largest element to find * @return the k-th largest element within the specified range in the input array * @throws IllegalArgumentException if the specified array/range is {@code null} or empty, its length is less than k * @throws IndexOutOfBoundsException if the range is out of the array bounds * @see #kthLargest(int[], int) */ public static long kthLargest(final long[] a, final int fromIndex, final int toIndex, int k) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } checkFromToIndex(fromIndex, toIndex, len(a)); checkArgument(k > 0 && k <= toIndex - fromIndex, "'k' (%s) is out of range %s", k, toIndex - fromIndex); final int len = toIndex - fromIndex; if (k == 1) { return max(a, fromIndex, toIndex); } else if (k == len) { return min(a, fromIndex, toIndex); } Queue queue = null; if (k <= len / 2) { queue = new PriorityQueue<>(k); for (int i = fromIndex; i < toIndex; i++) { if (queue.size() < k) { queue.add(a[i]); } else { if (a[i] > queue.peek()) { queue.remove(); queue.add(a[i]); } } } } else { k = len - k + 1; queue = new PriorityQueue<>(k, Comparator.reverseOrder()); for (int i = fromIndex; i < toIndex; i++) { if (queue.size() < k) { queue.add(a[i]); } else { //noinspection DataFlowIssue if (a[i] < queue.peek()) { queue.remove(); queue.add(a[i]); } } } } //noinspection DataFlowIssue return queue.peek(); } /** * Returns the k-th largest element in the specified array. * * @param a the array to find the k-th largest element in * @param k the position (1-based) of the largest element to find * @return the k-th largest element in the array * @throws IllegalArgumentException if the specified array/range is {@code null} or empty, its length is less than k * @see #kthLargest(int[], int) */ public static float kthLargest(final float[] a, final int k) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return kthLargest(a, 0, a.length, k); } /** * Returns the k-th largest element within the specified range in the input array. * * @param a the array to find the k-th largest element in * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @param k the position (1-based) of the largest element to find * @return the k-th largest element within the specified range in the input array * @throws IllegalArgumentException if the specified array/range is {@code null} or empty, its length is less than k * @throws IndexOutOfBoundsException if the range is out of the array bounds * @see #kthLargest(int[], int) */ public static float kthLargest(final float[] a, final int fromIndex, final int toIndex, int k) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } checkFromToIndex(fromIndex, toIndex, len(a)); checkArgument(k > 0 && k <= toIndex - fromIndex, "'k' (%s) is out of range %s", k, toIndex - fromIndex); final int len = toIndex - fromIndex; if (k == 1) { return max(a, fromIndex, toIndex); } else if (k == len) { return min(a, fromIndex, toIndex); } Queue queue = null; if (k <= len / 2) { queue = new PriorityQueue<>(k); for (int i = fromIndex; i < toIndex; i++) { if (queue.size() < k) { queue.add(a[i]); } else { if (Float.compare(a[i], queue.peek()) > 0) { queue.remove(); queue.add(a[i]); } } } } else { k = len - k + 1; queue = new PriorityQueue<>(k, Comparator.reverseOrder()); for (int i = fromIndex; i < toIndex; i++) { if (queue.size() < k) { queue.add(a[i]); } else { //noinspection DataFlowIssue if (Float.compare(a[i], queue.peek()) < 0) { queue.remove(); queue.add(a[i]); } } } } //noinspection DataFlowIssue return queue.peek(); } /** * Returns the k-th largest element in the specified array. * * @param a the array to find the k-th largest element in * @param k the position (1-based) of the largest element to find * @return the k-th largest element in the array * @throws IllegalArgumentException if the specified array/range is {@code null} or empty, its length is less than k * @see #kthLargest(int[], int) */ public static double kthLargest(final double[] a, final int k) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return kthLargest(a, 0, a.length, k); } /** * Returns the k-th largest element within the specified range in the input array. * * @param a the array to find the k-th largest element in * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @param k the position (1-based) of the largest element to find * @return the k-th largest element within the specified range in the input array * @throws IllegalArgumentException if the specified array/range is {@code null} or empty, its length is less than k * @throws IndexOutOfBoundsException if the range is out of the array bounds * @see #kthLargest(int[], int) */ public static double kthLargest(final double[] a, final int fromIndex, final int toIndex, int k) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } checkFromToIndex(fromIndex, toIndex, len(a)); checkArgument(k > 0 && k <= toIndex - fromIndex, "'k' (%s) is out of range %s", k, toIndex - fromIndex); final int len = toIndex - fromIndex; if (k == 1) { return max(a, fromIndex, toIndex); } else if (k == len) { return min(a, fromIndex, toIndex); } Queue queue = null; if (k <= len / 2) { queue = new PriorityQueue<>(k); for (int i = fromIndex; i < toIndex; i++) { if (queue.size() < k) { queue.add(a[i]); } else { if (Double.compare(a[i], queue.peek()) > 0) { queue.remove(); queue.add(a[i]); } } } } else { k = len - k + 1; queue = new PriorityQueue<>(k, Comparator.reverseOrder()); for (int i = fromIndex; i < toIndex; i++) { if (queue.size() < k) { queue.add(a[i]); } else { //noinspection DataFlowIssue if (Double.compare(a[i], queue.peek()) < 0) { queue.remove(); queue.add(a[i]); } } } } //noinspection DataFlowIssue return queue.peek(); } /** * Returns the k-th largest element in the specified array. * * @param a the array to find the k-th largest element in * @param k the position (1-based) of the largest element to find * @return the k-th largest element in the array * @throws IllegalArgumentException if the specified array/range is {@code null} or empty, its length is less than k * @see #kthLargest(int[], int) * @see Iterables#kthLargest(Comparable[], int) */ public static > T kthLargest(final T[] a, final int k) throws IllegalArgumentException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return kthLargest(a, 0, a.length, k); } /** * Returns the k-th largest element within the specified range in the input array. * * @param The type of the elements in the array. It must be a type that implements Comparable. * @param a The array from which to find the k-th largest element. * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @param k The position from the largest element to return. * @return The kth largest element from the array. * @throws IllegalArgumentException if the specified array/range is {@code null} or empty, its length is less than k * @see Iterables#kthLargest(Comparable[], int) */ public static > T kthLargest(final T[] a, final int fromIndex, final int toIndex, final int k) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } return kthLargest(a, fromIndex, toIndex, k, (Comparator) NULL_MIN_COMPARATOR); } /** * Returns the k-th largest element in the specified array according to the provided comparator. * * @param the type of elements in the input array * @param a the array to find the k-th largest element in * @param k the position (1-based) of the largest element to find * @param cmp the comparator to determine the order of the array * @return the k-th largest element in the array * @throws IllegalArgumentException if the specified array/range is {@code null} or empty, its length is less than k * @see #kthLargest(int[], int) * @see Iterables#kthLargest(Collection, int) */ public static T kthLargest(final T[] a, final int k, final Comparator cmp) throws IllegalArgumentException, IndexOutOfBoundsException { checkArgNotEmpty(a, "The specified array can not be null or empty"); return kthLargest(a, 0, a.length, k, cmp); } /** * Returns the k-th largest element within the specified range in the input array according to the provided comparator. * * @param The type of the elements in the array. * @param a The array from which to find the k-th largest element. * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @param k The position from the largest element to return. * @param cmp The comparator to determine the order of the array. * @return The kth largest element from the array. * @throws IllegalArgumentException if the specified array/range is {@code null} or empty, its length is less than k * @see #kthLargest(int[], int) * @see Iterables#kthLargest(Collection, int, Comparator) */ public static T kthLargest(final T[] a, final int fromIndex, final int toIndex, int k, final Comparator cmp) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(a) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The specified array can not be null or empty"); } checkFromToIndex(fromIndex, toIndex, len(a)); checkArgument(k > 0 && k <= toIndex - fromIndex, "'k' (%s) is out of range %s", k, toIndex - fromIndex); final Comparator comparator = cmp == null ? NULL_MIN_COMPARATOR : cmp; final int len = toIndex - fromIndex; if (k == 1) { return max(a, fromIndex, toIndex, comparator); } else if (k == len) { return min(a, fromIndex, toIndex, comparator); } Queue queue = null; if (k <= len / 2) { queue = new PriorityQueue<>(k, comparator); for (int i = fromIndex; i < toIndex; i++) { if (queue.size() < k) { queue.add(a[i]); } else { if (comparator.compare(a[i], queue.peek()) > 0) { queue.remove(); queue.add(a[i]); } } } } else { k = len - k + 1; queue = new PriorityQueue<>(k, (o1, o2) -> comparator.compare(o2, o1)); for (int i = fromIndex; i < toIndex; i++) { if (queue.size() < k) { queue.add(a[i]); } else { if (comparator.compare(a[i], queue.peek()) < 0) { queue.remove(); queue.add(a[i]); } } } } return queue.peek(); } /** * Returns the k-th largest element in the specified collection. * * @param c the collection to find the k-th largest element in * @param k the position (1-based) of the largest element to find * @return the k-th largest element in the array * @throws IllegalArgumentException if the specified collection/range is {@code null} or empty, its length is less than k * @see #kthLargest(int[], int) * @see Iterables#kthLargest(Collection, int) */ public static > T kthLargest(final Collection c, final int k) throws IllegalArgumentException { checkArgNotEmpty(c, "The specified collection can not be null or empty"); return kthLargest(c, 0, c.size(), k); } /** * Returns the k-th largest element within the specified range in the input collection. * * @param The type of the elements in the collection. * @param c The collection from which to find the k-th largest element. * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @param k The position from the largest element to return. * @return The kth largest element from the collection. * @throws IllegalArgumentException if the specified collection/range is {@code null} or empty, its length is less than k * @see #kthLargest(int[], int) * @see Iterables#kthLargest(Collection, int) */ public static > T kthLargest(final Collection c, final int fromIndex, final int toIndex, final int k) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(c) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The length of collection can not be null or empty"); } return kthLargest(c, fromIndex, toIndex, k, (Comparator) NULL_MIN_COMPARATOR); } /** * Returns the k-th largest element in the specified collection according to the provided comparator. * * @param the type of elements in the input collection * @param c the collection to find the k-th largest element in * @param k the position (1-based) of the largest element to find * @param cmp the comparator to determine the order of the collection * @return the k-th largest element in the collection * @throws IllegalArgumentException if the specified collection/range is {@code null} or empty, its length is less than k * @see #kthLargest(int[], int) * @see Iterables#kthLargest(Collection, int, Comparator) */ public static T kthLargest(final Collection c, final int k, final Comparator cmp) throws IllegalArgumentException, IndexOutOfBoundsException { checkArgNotEmpty(c, "The specified collection can not be null or empty"); return kthLargest(c, 0, c.size(), k, cmp); } /** * Returns the k-th largest element within the specified range in the input collection according to the provided comparator. * * @param The type of the elements in the collection. * @param c The collection from which to find the k-th largest element. * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @param k The position from the largest element to return. * @param cmp The comparator to determine the order of the collection. * @return The kth largest element from the collection. * @throws IllegalArgumentException if the specified collection/range is {@code null} or empty, its length is less than k * @see #kthLargest(int[], int) * @see Iterables#kthLargest(Collection, int, Comparator) */ public static T kthLargest(final Collection c, final int fromIndex, final int toIndex, int k, final Comparator cmp) throws IllegalArgumentException, IndexOutOfBoundsException { if (isEmpty(c) || toIndex - fromIndex < 1) { throw new IllegalArgumentException("The length of collection can not be null or empty"); } checkFromToIndex(fromIndex, toIndex, size(c)); checkArgument(k > 0 && k <= toIndex - fromIndex, "'k' (%s) is out of range %s", k, toIndex - fromIndex); final Comparator comparator = cmp == null ? NULL_MIN_COMPARATOR : cmp; final int len = toIndex - fromIndex; if (k == 1) { return max(c, fromIndex, toIndex, comparator); } else if (k == len) { return min(c, fromIndex, toIndex, comparator); } final Iterator iter = c.iterator(); Queue queue = null; if (k <= len / 2) { queue = new PriorityQueue<>(k); int cursor = 0; while (cursor < fromIndex && iter.hasNext()) { cursor++; iter.next(); } T e = null; while (cursor < toIndex && iter.hasNext()) { e = iter.next(); if (queue.size() < k) { queue.add(e); } else { if (comparator.compare(e, queue.peek()) > 0) { queue.remove(); queue.add(e); } } cursor++; } } else { k = len - k + 1; queue = new PriorityQueue<>(k, (o1, o2) -> comparator.compare(o2, o1)); int cursor = 0; while (cursor < fromIndex && iter.hasNext()) { cursor++; iter.next(); } T e = null; while (cursor < toIndex && iter.hasNext()) { e = iter.next(); if (queue.size() < k) { queue.add(e); } else { if (comparator.compare(e, queue.peek()) < 0) { queue.remove(); queue.add(e); } } cursor++; } } return queue.peek(); } /** * Returns the top n elements from the specified array. * If there are less than n elements in the array, a copy of the input array is returned. * * @param a the array to find the top n elements in * @param n the number of top elements to return * @return an array containing the top n elements * @throws IllegalArgumentException if the specified n is negative. * @see #top(int[], int) */ public static short[] top(final short[] a, final int n) { return top(a, n, null); } /** * Returns the top n elements from the specified array according to the provided comparator. * If there are less than n elements in the array, a copy of the input array is returned. * * @param a the array to find the top n elements in * @param n the number of top elements to return * @param cmp the comparator to determine the order of the array * @return an array containing the top n elements * @throws IllegalArgumentException if the specified n is negative. * @see #top(int[], int) */ public static short[] top(final short[] a, final int n, final Comparator cmp) { return top(a, 0, len(a), n, cmp); } /** * Returns the top n elements from a specified range in the input array. * If there are less than n elements within the specified range, all the elements from the range will be included in the returned array. * * @param a the array to select the top elements from. * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param n the number of top elements to select. * @return a array containing the top n elements from the specified range in the input array. * @throws IllegalArgumentException if the specified n is negative. * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #top(int[], int) */ public static short[] top(final short[] a, final int fromIndex, final int toIndex, final int n) throws IllegalArgumentException, IndexOutOfBoundsException { return top(a, fromIndex, toIndex, n, null); } /** * Returns the top n elements from a specified range in the input array according to the provided comparator. * If there are less than n elements within the specified range, all the elements from the range will be included in the returned array. * * @param a the array to select the top elements from. * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param n the number of top elements to select. * @param cmp the comparator to determine the order of the array. * @return a array containing the top n elements from the specified range in the input array. * @throws IllegalArgumentException if the specified n is negative. * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #top(int[], int) */ public static short[] top(final short[] a, final int fromIndex, final int toIndex, final int n, final Comparator cmp) throws IllegalArgumentException, IndexOutOfBoundsException { checkArgNotNegative(n, cs.n); checkFromToIndex(fromIndex, toIndex, a == null ? 0 : a.length); if (isEmpty(a) || n == 0) { return EMPTY_SHORT_ARRAY; } else if (n >= toIndex - fromIndex) { return copyOfRange(a, fromIndex, toIndex); } final Comparator comparator = cmp == null ? NULL_MIN_COMPARATOR : cmp; final Queue heap = new PriorityQueue<>(n, comparator); for (int i = fromIndex; i < toIndex; i++) { if (heap.size() >= n) { if (comparator.compare(heap.peek(), a[i]) < 0) { heap.poll(); heap.add(a[i]); } } else { heap.offer(a[i]); } } final Iterator iter = heap.iterator(); final short[] res = new short[n]; int idx = 0; while (iter.hasNext()) { res[idx++] = iter.next(); } return res; } /** * Returns the top n elements from the specified array. * If there are less than n elements in the array, a copy of the input array is returned. * * @param a the array to find the top n elements in * @param n the number of top elements to return * @return an array containing the top n elements * @throws IllegalArgumentException if the specified n is negative. */ public static int[] top(final int[] a, final int n) { return top(a, n, null); } /** * Returns the top n elements from the specified array according to the provided comparator. * If there are less than n elements in the array, a copy of the input array is returned. * * @param a the array to find the top n elements in * @param n the number of top elements to return * @param cmp the comparator to determine the order of the array * @return an array containing the top n elements * @throws IllegalArgumentException if the specified n is negative. */ public static int[] top(final int[] a, final int n, final Comparator cmp) { return top(a, 0, len(a), n, cmp); } /** * Returns the top n elements from a specified range in the input array. * If there are less than n elements within the specified range, all the elements from the range will be included in the returned array. * * @param a the array to select the top elements from. * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param n the number of top elements to select. * @return a array containing the top n elements from the specified range in the input array. * @throws IllegalArgumentException if the specified n is negative. * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #top(int[], int) */ public static int[] top(final int[] a, final int fromIndex, final int toIndex, final int n) throws IllegalArgumentException, IndexOutOfBoundsException { return top(a, fromIndex, toIndex, n, null); } /** * Returns the top n elements from a specified range in the input array according to the provided comparator. * If there are less than n elements within the specified range, all the elements from the range will be included in the returned array. * * @param a the array to select the top elements from. * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param n the number of top elements to select. * @param cmp the comparator to determine the order of the array. * @return a array containing the top n elements from the specified range in the input array. * @throws IllegalArgumentException if the specified n is negative. * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #top(int[], int) */ public static int[] top(final int[] a, final int fromIndex, final int toIndex, final int n, final Comparator cmp) throws IllegalArgumentException, IndexOutOfBoundsException { checkArgNotNegative(n, cs.n); checkFromToIndex(fromIndex, toIndex, a == null ? 0 : a.length); if (isEmpty(a) || n == 0) { return EMPTY_INT_ARRAY; } else if (n >= toIndex - fromIndex) { return copyOfRange(a, fromIndex, toIndex); } final Comparator comparator = cmp == null ? NULL_MIN_COMPARATOR : cmp; final Queue heap = new PriorityQueue<>(n, comparator); for (int i = fromIndex; i < toIndex; i++) { if (heap.size() >= n) { if (comparator.compare(heap.peek(), a[i]) < 0) { heap.poll(); heap.add(a[i]); } } else { heap.offer(a[i]); } } final Iterator iter = heap.iterator(); final int[] res = new int[n]; int idx = 0; while (iter.hasNext()) { res[idx++] = iter.next(); } return res; } /** * Returns the top n elements from the specified array. * If there are less than n elements in the array, a copy of the input array is returned. * * @param a the array to find the top n elements in * @param n the number of top elements to return * @return an array containing the top n elements * @throws IllegalArgumentException if the specified n is negative. * @see #top(int[], int) */ public static long[] top(final long[] a, final int n) { return top(a, n, null); } /** * Returns the top n elements from the specified array according to the provided comparator. * If there are less than n elements in the array, a copy of the input array is returned. * * @param a the array to find the top n elements in * @param n the number of top elements to return * @param cmp the comparator to determine the order of the array * @return an array containing the top n elements * @throws IllegalArgumentException if the specified n is negative. * @see #top(int[], int) */ public static long[] top(final long[] a, final int n, final Comparator cmp) { return top(a, 0, len(a), n, cmp); } /** * Returns the top n elements from a specified range in the input array. * If there are less than n elements within the specified range, all the elements from the range will be included in the returned array. * * @param a the array to select the top elements from. * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param n the number of top elements to select. * @return a array containing the top n elements from the specified range in the input array. * @throws IllegalArgumentException if the specified n is negative. * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #top(int[], int) */ public static long[] top(final long[] a, final int fromIndex, final int toIndex, final int n) throws IllegalArgumentException, IndexOutOfBoundsException { return top(a, fromIndex, toIndex, n, null); } /** * Returns the top n elements from a specified range in the input array according to the provided comparator. * If there are less than n elements within the specified range, all the elements from the range will be included in the returned array. * * @param a the array to select the top elements from. * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param n the number of top elements to select. * @param cmp the comparator to determine the order of the array. * @return a array containing the top n elements from the specified range in the input array. * @throws IllegalArgumentException if the specified n is negative. * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #top(int[], int) */ public static long[] top(final long[] a, final int fromIndex, final int toIndex, final int n, final Comparator cmp) throws IllegalArgumentException, IndexOutOfBoundsException { checkArgNotNegative(n, cs.n); checkFromToIndex(fromIndex, toIndex, a == null ? 0 : a.length); if (isEmpty(a) || n == 0) { return EMPTY_LONG_ARRAY; } else if (n >= toIndex - fromIndex) { return copyOfRange(a, fromIndex, toIndex); } final Comparator comparator = cmp == null ? NULL_MIN_COMPARATOR : cmp; final Queue heap = new PriorityQueue<>(n, comparator); for (int i = fromIndex; i < toIndex; i++) { if (heap.size() >= n) { if (comparator.compare(heap.peek(), a[i]) < 0) { heap.poll(); heap.add(a[i]); } } else { heap.offer(a[i]); } } final Iterator iter = heap.iterator(); final long[] res = new long[n]; int idx = 0; while (iter.hasNext()) { res[idx++] = iter.next(); } return res; } /** * Returns the top n elements from the specified array. * If there are less than n elements in the array, a copy of the input array is returned. * * @param a the array to find the top n elements in * @param n the number of top elements to return * @return an array containing the top n elements * @throws IllegalArgumentException if the specified n is negative. * @see #top(int[], int) */ public static float[] top(final float[] a, final int n) { return top(a, n, null); } /** * Returns the top n elements from the specified array according to the provided comparator. * If there are less than n elements in the array, a copy of the input array is returned. * * @param a the array to find the top n elements in * @param n the number of top elements to return * @param cmp the comparator to determine the order of the array * @return an array containing the top n elements * @throws IllegalArgumentException if the specified n is negative. * @see #top(int[], int) */ public static float[] top(final float[] a, final int n, final Comparator cmp) { return top(a, 0, len(a), n, cmp); } /** * Returns the top n elements from a specified range in the input array. * If there are less than n elements within the specified range, all the elements from the range will be included in the returned array. * * @param a the array to select the top elements from. * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param n the number of top elements to select. * @return a array containing the top n elements from the specified range in the input array. * @throws IllegalArgumentException if the specified n is negative. * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #top(int[], int) */ public static float[] top(final float[] a, final int fromIndex, final int toIndex, final int n) throws IllegalArgumentException, IndexOutOfBoundsException { return top(a, fromIndex, toIndex, n, null); } /** * Returns the top n elements from a specified range in the input array according to the provided comparator. * If there are less than n elements within the specified range, all the elements from the range will be included in the returned array. * * @param a the array to select the top elements from. * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param n the number of top elements to select. * @param cmp the comparator to determine the order of the array. * @return a array containing the top n elements from the specified range in the input array. * @throws IllegalArgumentException if the specified n is negative. * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #top(int[], int) */ public static float[] top(final float[] a, final int fromIndex, final int toIndex, final int n, final Comparator cmp) throws IllegalArgumentException, IndexOutOfBoundsException { checkArgNotNegative(n, cs.n); checkFromToIndex(fromIndex, toIndex, a == null ? 0 : a.length); if (isEmpty(a) || n == 0) { return EMPTY_FLOAT_ARRAY; } else if (n >= toIndex - fromIndex) { return copyOfRange(a, fromIndex, toIndex); } final Comparator comparator = cmp == null ? NULL_MIN_COMPARATOR : cmp; final Queue heap = new PriorityQueue<>(n, comparator); for (int i = fromIndex; i < toIndex; i++) { if (heap.size() >= n) { if (comparator.compare(heap.peek(), a[i]) < 0) { heap.poll(); heap.add(a[i]); } } else { heap.offer(a[i]); } } final Iterator iter = heap.iterator(); final float[] res = new float[n]; int idx = 0; while (iter.hasNext()) { res[idx++] = iter.next(); } return res; } /** * Returns the top n elements from the specified array. * If there are less than n elements in the array, a copy of the input array is returned. * * @param a the array to find the top n elements in * @param n the number of top elements to return * @return an array containing the top n elements * @throws IllegalArgumentException if the specified n is negative. * @see #top(int[], int) */ public static double[] top(final double[] a, final int n) { return top(a, n, null); } /** * Returns the top n elements from the specified array according to the provided comparator. * If there are less than n elements in the array, a copy of the input array is returned. * * @param a the array to find the top n elements in * @param n the number of top elements to return * @param cmp the comparator to determine the order of the array * @return an array containing the top n elements * @throws IllegalArgumentException if the specified n is negative. * @see #top(int[], int) */ public static double[] top(final double[] a, final int n, final Comparator cmp) { return top(a, 0, len(a), n, cmp); } /** * Returns the top n elements from a specified range in the input array. * If there are less than n elements within the specified range, all the elements from the range will be included in the returned array. * * @param a the array to select the top elements from. * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param n the number of top elements to select. * @return a array containing the top n elements from the specified range in the input array. * @throws IllegalArgumentException if the specified n is negative. * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #top(int[], int) */ public static double[] top(final double[] a, final int fromIndex, final int toIndex, final int n) throws IllegalArgumentException, IndexOutOfBoundsException { return top(a, fromIndex, toIndex, n, null); } /** * Returns the top n elements from a specified range in the input array according to the provided comparator. * If there are less than n elements within the specified range, all the elements from the range will be included in the returned array. * * @param a the array to select the top elements from. * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param n the number of top elements to select. * @param cmp the comparator to determine the order of the array. * @return a array containing the top n elements from the specified range in the input array. * @throws IllegalArgumentException if the specified n is negative. * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #top(int[], int) */ public static double[] top(final double[] a, final int fromIndex, final int toIndex, final int n, final Comparator cmp) throws IllegalArgumentException, IndexOutOfBoundsException { checkArgNotNegative(n, cs.n); checkFromToIndex(fromIndex, toIndex, a == null ? 0 : a.length); if (isEmpty(a) || n == 0) { return EMPTY_DOUBLE_ARRAY; } else if (n >= toIndex - fromIndex) { return copyOfRange(a, fromIndex, toIndex); } final Comparator comparator = cmp == null ? NULL_MIN_COMPARATOR : cmp; final Queue heap = new PriorityQueue<>(n, comparator); for (int i = fromIndex; i < toIndex; i++) { if (heap.size() >= n) { if (comparator.compare(heap.peek(), a[i]) < 0) { heap.poll(); heap.add(a[i]); } } else { heap.offer(a[i]); } } final Iterator iter = heap.iterator(); final double[] res = new double[n]; int idx = 0; while (iter.hasNext()) { res[idx++] = iter.next(); } return res; } /** * Returns the top n elements from the specified array based on their natural ordering. Null values are considered as the smallest elements here. * If there are less than n elements in the array, all the elements will be included to returned list. * * @param The type of the elements in the array. It must be a type that implements Comparable. * @param a The array from which to find the top n elements. * @param n The number of top elements to return. * @return A list containing the top n elements from the array. * @throws IllegalArgumentException if the specified n is negative. * @see #top(int[], int) */ public static > List top(final T[] a, final int n) { return top(a, n, NULL_MIN_COMPARATOR); } /** * Returns the top n elements from the specified array according to the provided comparator. * If there are less than n elements in the array, all the elements will be included to returned list. * * @param The type of the elements in the array. * @param a The array from which to find the top n elements. * @param n The number of top elements to return. * @param cmp The Comparator to determine the order of the elements. * @return A list containing the top n elements from the array. * @throws IllegalArgumentException if the specified n is negative. * @see #top(int[], int) */ public static List top(final T[] a, final int n, final Comparator cmp) { return top(a, 0, len(a), n, cmp); } /** * Returns the top n elements from the specified range in the input array based on their natural ordering. Null values are considered as the smallest elements here. * If there are less than n elements in the range specified by {@code fromIndex} and {@code toIndex}, all the elements from that range will be included to returned list. * * @param The type of the elements in the array. It must be a type that implements Comparable. * @param a The array from which to find the top n elements. * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @param n The number of top elements to return. * @return A list containing the top n elements from the specified range in the input array. * @throws IllegalArgumentException if the specified n is negative. * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #top(int[], int) */ public static > List top(final T[] a, final int fromIndex, final int toIndex, final int n) throws IllegalArgumentException, IndexOutOfBoundsException { return top(a, fromIndex, toIndex, n, NULL_MIN_COMPARATOR); } /** * Returns the top n elements from the specified range in the input array according to the provided comparator. * If there are less than n elements in the range, all the elements from that range will be included in the returned list. * * @param The type of the elements in the array. * @param a The array from which to find the top n elements. * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @param n The number of top elements to return. * @param cmp The comparator to determine the order of the elements. * @return A list containing the top n elements from the specified range in the input array. * @throws IllegalArgumentException if the specified n is negative. * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #top(int[], int) */ @SuppressWarnings("deprecation") public static List top(final T[] a, final int fromIndex, final int toIndex, final int n, final Comparator cmp) throws IllegalArgumentException, IndexOutOfBoundsException { checkArgNotNegative(n, cs.n); checkFromToIndex(fromIndex, toIndex, a == null ? 0 : a.length); if (isEmpty(a) || n == 0) { return new ArrayList<>(); } else if (n >= toIndex - fromIndex) { return toList(a, fromIndex, toIndex); } final Comparator comparator = cmp == null ? NULL_MIN_COMPARATOR : cmp; final Queue heap = new PriorityQueue<>(n, comparator); for (int i = fromIndex; i < toIndex; i++) { if (heap.size() >= n) { if (comparator.compare(heap.peek(), a[i]) < 0) { heap.poll(); heap.add(a[i]); } } else { heap.offer(a[i]); } } return InternalUtil.createList((T[]) heap.toArray(EMPTY_OBJECT_ARRAY)); } /** * Returns the top n elements from the specified collection based on their natural ordering. Null values are considered as the smallest elements here. * If there are less than n elements in the collection, all the elements will be included to returned list. * * @param The type of the elements in the collection. It must be a type that implements Comparable. * @param c the collection from which to find the top n elements. * @param n The number of top elements to return. * @return A list containing the top n elements from the collection. * @throws IllegalArgumentException if the specified n is negative. * @see #top(int[], int) */ public static > List top(final Collection c, final int n) { return top(c, n, null); } /** * Returns the top n elements from the specified collection according to the provided comparator. * If there are less than n elements in the collection, all the elements will be included to returned list. * * @param The type of the elements in the collection. * @param c the collection from which to find the top n elements. * @param n The number of top elements to return. * @param cmp The comparator to determine the order of the elements. * @return A list containing the top n elements from the collection. * @throws IllegalArgumentException if the specified n is negative. * @see #top(int[], int) */ public static List top(final Collection c, final int n, final Comparator cmp) { return top(c, 0, size(c), n, cmp); } /** * Returns the top n elements from the specified range in the input collection based on their natural ordering. Null values are considered as the smallest elements here. * If there are less than n elements in the range specified by {@code fromIndex} and {@code toIndex}, all the elements from that range will be included to returned list. * * @param The type of the elements in the collection. It must be a type that implements Comparable. * @param c the collection from which to find the top n elements. * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @param n The number of top elements to return. * @return A list containing the top n elements from the specified range in the input collection. * @throws IllegalArgumentException if the specified n is negative. * @throws IndexOutOfBoundsException if the specified range is out of the collection's bounds. * @see #top(int[], int) */ public static > List top(final Collection c, final int fromIndex, final int toIndex, final int n) throws IllegalArgumentException, IndexOutOfBoundsException { return top(c, fromIndex, toIndex, n, null); } /** * Returns the top n elements from the specified range in the input collection according to the provided comparator. * If there are less than n elements in the range, all the elements from that range will be included in the returned list. * * @param The type of the elements in the collection. * @param c the collection from which to find the top n elements. * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @param n The number of top elements to return. * @param cmp The comparator to determine the order of the elements. * @return A list containing the top n elements from the specified range in the input collection. * @throws IllegalArgumentException if the specified n is negative. * @throws IndexOutOfBoundsException if the specified range is out of the collection's bounds. * @see #top(int[], int) */ @SuppressWarnings("deprecation") public static List top(final Collection c, final int fromIndex, final int toIndex, final int n, final Comparator cmp) throws IllegalArgumentException, IndexOutOfBoundsException { checkArgNotNegative(n, cs.n); checkFromToIndex(fromIndex, toIndex, c == null ? 0 : c.size()); if (isEmpty(c) || n == 0) { return new ArrayList<>(); } else if (n >= toIndex - fromIndex) { if (fromIndex == 0 && toIndex == c.size()) { return new ArrayList<>(c); } else { final List res = new ArrayList<>(toIndex - fromIndex); final Iterator iter = c.iterator(); T e = null; for (int i = 0; i < toIndex && iter.hasNext(); i++) { e = iter.next(); if (i < fromIndex) { continue; } res.add(e); } return res; } } final Comparator comparator = cmp == null ? NULL_MIN_COMPARATOR : cmp; final Queue heap = new PriorityQueue<>(n, comparator); if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; T e = null; for (int i = fromIndex; i < toIndex; i++) { e = list.get(i); if (heap.size() >= n) { if (comparator.compare(heap.peek(), e) < 0) { heap.poll(); heap.add(e); } } else { heap.offer(e); } } } else { final Iterator iter = c.iterator(); T e = null; for (int i = 0; i < toIndex && iter.hasNext(); i++) { e = iter.next(); if (i < fromIndex) { continue; } if (heap.size() >= n) { if (comparator.compare(heap.peek(), e) < 0) { heap.poll(); heap.add(e); } } else { heap.offer(e); } } } return InternalUtil.createList((T[]) heap.toArray(EMPTY_OBJECT_ARRAY)); } /** * Returns the top n elements from the specified array based on their natural ordering. Null values are considered as the smallest elements here. * If there are less than n elements in the array, all the elements will be included to returned list. * The order of the elements in the returned list is based on their encounter order in the array if keepEncounterOrder is {@code true}. * * @param The type of the elements in the array. It must be a type that implements Comparable. * @param a The array from which to find the top n elements. * @param n The number of top elements to return. * @return A list containing the top n elements from the array. * @param keepEncounterOrder If it's {@code true}, the encounter order of the elements in the array is preserved in the returned list. * @throws IllegalArgumentException if the specified n is negative. * @see #top(int[], int) */ public static > List top(final T[] a, final int n, final boolean keepEncounterOrder) { return top(a, n, NULL_MIN_COMPARATOR, keepEncounterOrder); } /** * Returns the top n elements from the specified array according to the provided comparator. * If there are less than n elements in the array, all the elements will be included to returned list. * The order of the elements in the returned list is based on their encounter order in the array if keepEncounterOrder is {@code true}. * * @param The type of the elements in the array. * @param a The array from which to find the top n elements. * @param n The number of top elements to return. * @param cmp The comparator to determine the order of the elements. * @param keepEncounterOrder If it's {@code true}, the encounter order of the elements in the array is preserved in the returned list. * @return A list containing the top n elements from the array. * @throws IllegalArgumentException if the specified n is negative. * @see #top(int[], int) */ public static List top(final T[] a, final int n, final Comparator cmp, final boolean keepEncounterOrder) { return top(a, 0, len(a), n, cmp, keepEncounterOrder); } /** * Returns the top n elements from the specified range in the input array based on their natural ordering. Null values are considered as the smallest elements here. * If there are less than n elements in the range specified by {@code fromIndex} and {@code toIndex}, all the elements from that range will be included to returned list. * The order of the elements in the returned list is based on their encounter order in the array if keepEncounterOrder is {@code true}. * * @param The type of the elements in the array. It must be a type that implements Comparable. * @param a The array from which to find the top n elements. * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @param n The number of top elements to return. * @param keepEncounterOrder If it's {@code true}, the encounter order of the elements in the array is preserved in the returned list. * @return A list containing the top n elements from the specified range in the input array. * @throws IllegalArgumentException if the specified n is negative. * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #top(int[], int) */ public static > List top(final T[] a, final int fromIndex, final int toIndex, final int n, final boolean keepEncounterOrder) throws IllegalArgumentException, IndexOutOfBoundsException { return top(a, fromIndex, toIndex, n, NULL_MIN_COMPARATOR, keepEncounterOrder); } /** * Returns the top n elements from the specified range in the input array according to the provided comparator. * If there are less than n elements in the range, all the elements from that range will be included in the returned list. * The order of the elements in the returned list is based on their encounter order in the array if keepEncounterOrder is {@code true}. * * @param The type of the elements in the array. * @param a The array from which to find the top n elements. * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @param n The number of top elements to return. * @param cmp The comparator to determine the order of the elements. * @param keepEncounterOrder If it's {@code true}, the encounter order of the elements in the array is preserved in the returned list. * @return A list containing the top n elements from the specified range in the input array. * @throws IllegalArgumentException if the specified n is negative. * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #top(int[], int) */ public static List top(final T[] a, final int fromIndex, final int toIndex, final int n, final Comparator cmp, final boolean keepEncounterOrder) throws IllegalArgumentException, IndexOutOfBoundsException { checkArgNotNegative(n, cs.n); checkFromToIndex(fromIndex, toIndex, a == null ? 0 : a.length); if (!keepEncounterOrder) { return top(a, fromIndex, toIndex, n, cmp); } if (isEmpty(a) || n == 0) { return new ArrayList<>(); } else if (n >= toIndex - fromIndex) { return toList(a, fromIndex, toIndex); } final Comparator> comparator = createComparatorForIndexedObject(cmp); final Queue> heap = new PriorityQueue<>(n, comparator); Indexed indexed = null; for (int i = fromIndex; i < toIndex; i++) { indexed = Indexed.of(a[i], i); if (heap.size() >= n) { if (comparator.compare(heap.peek(), indexed) < 0) { heap.poll(); heap.add(indexed); } } else { heap.offer(indexed); } } final Indexed[] arrayOfIndexed = heap.toArray(new Indexed[0]); sort(arrayOfIndexed, Comparator.comparingInt(Indexed::index)); final List res = new ArrayList<>(arrayOfIndexed.length); for (final Indexed element : arrayOfIndexed) { res.add(element.value()); } return res; } @SuppressWarnings("rawtypes") private static Comparator> createComparatorForIndexedObject(final Comparator cmp) { Comparator> pairCmp = null; if (cmp != null) { pairCmp = (a, b) -> cmp.compare(a.value(), b.value()); } else { final Comparator> tmp = (a, b) -> compare(a.value(), b.value()); pairCmp = (Comparator) tmp; } return pairCmp; } /** * Returns the top n elements from the specified collection based on their natural ordering. Null values are considered as the smallest elements here. * If there are less than n elements in the collection, all the elements will be included to returned list. * The order of the elements in the returned list is based on their encounter order in the collection if keepEncounterOrder is {@code true}. * * @param The type of the elements in the collection. The type must be a subclass of {@link Comparable}. * @param c The collection from which to find the top n elements. * @param n The number of top elements to return. * @return A list containing the top n elements from the collection. * @param keepEncounterOrder If it's {@code true}, the encounter order of the elements in the collection is preserved in the returned list. * @throws IllegalArgumentException if the specified n is negative. * @see #top(int[], int) */ public static > List top(final Collection c, final int n, final boolean keepEncounterOrder) { return top(c, n, NULL_MIN_COMPARATOR, keepEncounterOrder); } /** * Returns the top n elements from the specified collection according to the provided comparator. * If there are less than n elements in the collection, all the elements will be included to returned list. * The order of the elements in the returned list is based on their encounter order in the collection if keepEncounterOrder is {@code true}. * * @param The type of the elements in the collection. * @param c The collection from which to find the top n elements. * @param n The number of top elements to return. * @param cmp The comparator to determine the order of the elements. * @return A list containing the top n elements from the collection. * @param keepEncounterOrder If it's {@code true}, the encounter order of the elements in the collection is preserved in the returned list. * @throws IllegalArgumentException if the specified n is negative. * @see #top(int[], int) */ public static List top(final Collection c, final int n, final Comparator cmp, final boolean keepEncounterOrder) { return top(c, 0, size(c), n, cmp, keepEncounterOrder); } /** * Returns the top n elements from the specified range in the input collection based on their natural ordering. Null values are considered as the smallest elements here. * If there are less than n elements in the range specified by {@code fromIndex} and {@code toIndex}, all the elements from that range will be included to returned list. * The order of the elements in the returned list is based on their encounter order in the collection if keepEncounterOrder is {@code true}. * * @param The type of the elements in the collection. The type must be a subclass of {@link Comparable}. * @param c The collection from which to find the top n elements. * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @param n The number of top elements to return. * @return A list containing the top n elements from the specified range in the input collection. * @param keepEncounterOrder If it's {@code true}, the encounter order of the elements in the collection is preserved in the returned list. * @throws IllegalArgumentException if the specified n is negative. * @throws IndexOutOfBoundsException if the specified range is out of the collection's bounds. * @see #top(int[], int) */ public static > List top(final Collection c, final int fromIndex, final int toIndex, final int n, final boolean keepEncounterOrder) throws IllegalArgumentException, IndexOutOfBoundsException { return top(c, fromIndex, toIndex, n, NULL_MIN_COMPARATOR, keepEncounterOrder); } /** * Returns the top n elements from the specified range in the input collection according to the provided comparator. * If there are less than n elements in the range, all the elements from that range will be included in the returned list. * The order of the elements in the returned list is based on their encounter order in the collection if keepEncounterOrder is {@code true}. * * @param The type of the elements in the collection. * @param c The collection from which to find the top n elements. * @param fromIndex The start index (inclusive) of the range * @param toIndex the end index (exclusive) of the range * @param n The number of top elements to return. * @param cmp The comparator to determine the order of the elements. * @param keepEncounterOrder If it's {@code true}, the encounter order of the elements in the collection is preserved in the returned list. * @return A list containing the top n elements from the specified range in the input collection. * @throws IllegalArgumentException if the specified n is negative. * @throws IndexOutOfBoundsException if the specified range is out of the collection's bounds. * @see #top(int[], int) */ public static List top(final Collection c, final int fromIndex, final int toIndex, final int n, final Comparator cmp, final boolean keepEncounterOrder) throws IllegalArgumentException, IndexOutOfBoundsException { checkArgNotNegative(n, cs.n); checkFromToIndex(fromIndex, toIndex, c == null ? 0 : c.size()); if (!keepEncounterOrder) { return top(c, fromIndex, toIndex, n, cmp); } if (isEmpty(c) || n == 0) { return new ArrayList<>(); } else if (n >= toIndex - fromIndex) { if (fromIndex == 0 && toIndex == c.size()) { return new ArrayList<>(c); } else { final List res = new ArrayList<>(toIndex - fromIndex); final Iterator iter = c.iterator(); T e = null; for (int i = 0; i < toIndex && iter.hasNext(); i++) { e = iter.next(); if (i < fromIndex) { continue; } res.add(e); } return res; } } final Comparator> comparator = createComparatorForIndexedObject(cmp); final Queue> heap = new PriorityQueue<>(n, comparator); if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; Indexed indexed = null; T e = null; for (int i = fromIndex; i < toIndex; i++) { e = list.get(i); indexed = Indexed.of(e, i); if (heap.size() >= n) { if (comparator.compare(heap.peek(), indexed) < 0) { heap.poll(); heap.add(indexed); } } else { heap.offer(indexed); } } } else { final Iterator iter = c.iterator(); Indexed indexed = null; T e = null; for (int i = 0; i < toIndex && iter.hasNext(); i++) { e = iter.next(); if (i < fromIndex) { continue; } indexed = Indexed.of(e, i); if (heap.size() >= n) { if (comparator.compare(heap.peek(), indexed) < 0) { heap.poll(); heap.add(indexed); } } else { heap.offer(indexed); } } } final Indexed[] arrayOfIndexed = heap.toArray(new Indexed[0]); sort(arrayOfIndexed, Comparator.comparingInt(Indexed::index)); final List res = new ArrayList<>(arrayOfIndexed.length); for (final Indexed element : arrayOfIndexed) { res.add(element.value()); } return res; } /** * Calculates the percentiles of the provided sorted array of characters. * * @param sortedArray The sorted array of characters for which to calculate the percentiles. * @return A map where the keys are the percentiles and the values are the corresponding characters from the array. * @throws IllegalArgumentException if the provided array is empty. * @see #percentiles(int[]) */ public static Map percentiles(final char[] sortedArray) throws IllegalArgumentException { checkArgNotEmpty(sortedArray, "The specified 'sortedArray' can not be null or empty"); //NOSONAR final int len = sortedArray.length; final Map m = newLinkedHashMap(Percentage.values().length); for (final Percentage p : Percentage.values()) { m.put(p, sortedArray[(int) (len * p.doubleValue())]); } return m; } /** * Calculates the percentiles of the provided sorted array of bytes. * * @param sortedArray The sorted array of bytes for which to calculate the percentiles. * @return A map where the keys are the percentiles and the values are the corresponding bytes from the array. * @throws IllegalArgumentException if the provided array is empty. * @see #percentiles(int[]) */ public static Map percentiles(final byte[] sortedArray) throws IllegalArgumentException { checkArgNotEmpty(sortedArray, "The specified 'sortedArray' can not be null or empty"); final int len = sortedArray.length; final Map m = newLinkedHashMap(Percentage.values().length); for (final Percentage p : Percentage.values()) { m.put(p, sortedArray[(int) (len * p.doubleValue())]); } return m; } /** * Calculates the percentiles of the provided sorted array of shorts. * * @param sortedArray The sorted array of shorts for which to calculate the percentiles. * @return A map where the keys are the percentiles and the values are the corresponding shorts from the array. * @throws IllegalArgumentException if the provided array is empty. * @see #percentiles(int[]) */ public static Map percentiles(final short[] sortedArray) throws IllegalArgumentException { checkArgNotEmpty(sortedArray, "The specified 'sortedArray' can not be null or empty"); final int len = sortedArray.length; final Map m = newLinkedHashMap(Percentage.values().length); for (final Percentage p : Percentage.values()) { m.put(p, sortedArray[(int) (len * p.doubleValue())]); } return m; } /** * Calculates the percentiles of the provided sorted array of integers. *
     * 
     * final int[] sortedArray = Array.range(1, 101);
     * final Map percentiles = N.percentiles(a);
     * percentiles.forEach(Fn.println("="));
     *                     0.0001%=1
     *                     0.001%=1
     *                     0.01%=1
     *                     0.1%=1
     *                     1%=2
     *                     2%=3
     *                     3%=4
     *                     4%=5
     *                     5%=6
     *                     6%=7
     *                     7%=8
     *                     8%=9
     *                     9%=10
     *                     10%=11
     *                     20%=21
     *                     30%=31
     *                     40%=41
     *                     50%=51
     *                     60%=61
     *                     70%=71
     *                     80%=81
     *                     90%=91
     *                     91%=92
     *                     92%=93
     *                     93%=94
     *                     94%=95
     *                     95%=96
     *                     96%=97
     *                     97%=98
     *                     98%=99
     *                     99%=100
     *                     99.9%=100
     *                     99.99%=100
     *                     99.999%=100
     *                     99.9999%=100
     * 
     * 
* * @param sortedArray The sorted array of integers for which to calculate the percentiles. * @return A map where the keys are the percentiles and the values are the corresponding integers from the array. * @throws IllegalArgumentException if the provided array is empty. */ public static Map percentiles(final int[] sortedArray) throws IllegalArgumentException { checkArgNotEmpty(sortedArray, "The specified 'sortedArray' can not be null or empty"); final int len = sortedArray.length; final Map m = newLinkedHashMap(Percentage.values().length); for (final Percentage p : Percentage.values()) { m.put(p, sortedArray[(int) (len * p.doubleValue())]); } return m; } /** * Calculates the percentiles of the provided sorted array of longs. * * @param sortedArray The sorted array of longs for which to calculate the percentiles. * @return A map where the keys are the percentiles and the values are the corresponding longs from the array. * @throws IllegalArgumentException if the provided array is empty. * @see #percentiles(int[]) */ public static Map percentiles(final long[] sortedArray) throws IllegalArgumentException { checkArgNotEmpty(sortedArray, "The specified 'sortedArray' can not be null or empty"); final int len = sortedArray.length; final Map m = newLinkedHashMap(Percentage.values().length); for (final Percentage p : Percentage.values()) { m.put(p, sortedArray[(int) (len * p.doubleValue())]); } return m; } /** * Calculates the percentiles of the provided sorted array of floats. * * @param sortedArray The sorted array of floats for which to calculate the percentiles. * @return A map where the keys are the percentiles and the values are the corresponding floats from the array. * @throws IllegalArgumentException if the provided array is empty. * @see #percentiles(int[]) */ public static Map percentiles(final float[] sortedArray) throws IllegalArgumentException { checkArgNotEmpty(sortedArray, "The specified 'sortedArray' can not be null or empty"); final int len = sortedArray.length; final Map m = newLinkedHashMap(Percentage.values().length); for (final Percentage p : Percentage.values()) { m.put(p, sortedArray[(int) (len * p.doubleValue())]); } return m; } /** * Calculates the percentiles of the provided sorted array of doubles. * * @param sortedArray The sorted array of doubles for which to calculate the percentiles. * @return A map where the keys are the percentiles and the values are the corresponding doubles from the array. * @throws IllegalArgumentException if the provided array is empty. * @see #percentiles(int[]) */ public static Map percentiles(final double[] sortedArray) throws IllegalArgumentException { checkArgNotEmpty(sortedArray, "The specified 'sortedArray' can not be null or empty"); final int len = sortedArray.length; final Map m = newLinkedHashMap(Percentage.values().length); for (final Percentage p : Percentage.values()) { m.put(p, sortedArray[(int) (len * p.doubleValue())]); } return m; } /** * Calculates the percentiles of the provided sorted array. * * @param The type of elements in the array. * @param sortedArray The array for which to calculate the percentiles. * @return A map where the keys are the percentiles and the values are the corresponding elements from the array. * @throws IllegalArgumentException if the provided array is {@code null} or empty. * @see #percentiles(int[]) */ public static Map percentiles(final T[] sortedArray) throws IllegalArgumentException { checkArgNotEmpty(sortedArray, "The specified 'sortedArray' can not be null or empty"); final int len = sortedArray.length; final Map m = newLinkedHashMap(Percentage.values().length); for (final Percentage p : Percentage.values()) { m.put(p, sortedArray[(int) (len * p.doubleValue())]); } return m; } /** * Calculates the percentiles of the provided sorted list. * * @param The type of elements in the list. * @param sortedList The sorted list for which to calculate the percentiles. * @return A map where the keys are the percentiles and the values are the corresponding elements from the list. * @throws IllegalArgumentException if the provided list is {@code null} or empty. * @see #percentiles(int[]) */ public static Map percentiles(final List sortedList) throws IllegalArgumentException { checkArgNotEmpty(sortedList, "The specified 'sortedList' can not be null or empty"); final int size = sortedList.size(); final Map m = newLinkedHashMap(Percentage.values().length); for (final Percentage p : Percentage.values()) { m.put(p, sortedList.get((int) (size * p.doubleValue()))); } return m; } /** * Returns a new array containing only the elements that match the filter predicate. * An empty array is returned if the input array is empty. * * @param a the array of boolean values to be filtered * @param filter the predicate used to filter the array * @return a new array containing only the elements that match the filter predicate * @see #filter(int[], IntPredicate) */ public static boolean[] filter(final boolean[] a, final BooleanPredicate filter) { if (isEmpty(a)) { return EMPTY_BOOLEAN_ARRAY; } return filter(a, 0, a.length, filter); } /** * Returns a new array containing only the elements that match the filter predicate within the specified range in the input array. * An empty array is returned if the input array/range is empty. * * @param a the array of characters to be filtered * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param filter the predicate used to filter the array * @return a a new array containing only the elements that match the filter predicate within the specified range * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #filter(int[], IntPredicate) */ public static boolean[] filter(final boolean[] a, final int fromIndex, final int toIndex, final BooleanPredicate filter) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_BOOLEAN_ARRAY; } boolean[] result = new boolean[(toIndex - fromIndex) / 2]; int len = result.length; int count = 0; for (int i = fromIndex; i < toIndex; i++) { if (filter.test(a[i])) { if (count == len) { result = copyOf(result, toIndex - fromIndex); len = result.length; } result[count++] = a[i]; } } return result.length == count ? result : copyOfRange(result, 0, count); } /** * Returns a new array containing only the elements that match the filter predicate. * An empty array is returned if the input array is empty. * * @param a the array of characters to be filtered * @param filter the predicate used to filter the array * @return a new array containing only the elements that match the filter predicate * @see #filter(int[], IntPredicate) */ public static char[] filter(final char[] a, final CharPredicate filter) { if (isEmpty(a)) { return EMPTY_CHAR_ARRAY; } return filter(a, 0, a.length, filter); } /** * Returns a new array containing only the elements that match the filter predicate within the specified range in the input array. * An empty array is returned if the input array/range is empty. * * @param a the array of characters to be filtered * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param filter the predicate used to filter the array * @return a a new array containing only the elements that match the filter predicate within the specified range * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #filter(int[], IntPredicate) */ public static char[] filter(final char[] a, final int fromIndex, final int toIndex, final CharPredicate filter) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_CHAR_ARRAY; } char[] result = new char[(toIndex - fromIndex) / 2]; int len = result.length; int count = 0; for (int i = fromIndex; i < toIndex; i++) { if (filter.test(a[i])) { if (count == len) { result = copyOf(result, toIndex - fromIndex); len = result.length; } result[count++] = a[i]; } } return result.length == count ? result : copyOfRange(result, 0, count); } /** * Returns a new array containing only the elements that match the filter predicate. * An empty array is returned if the input array is empty. * * @param a the array of bytes to be filtered * @param filter the predicate used to filter the array * @return a new array containing only the elements that match the filter predicate * @see #filter(int[], IntPredicate) */ public static byte[] filter(final byte[] a, final BytePredicate filter) { if (isEmpty(a)) { return EMPTY_BYTE_ARRAY; } return filter(a, 0, a.length, filter); } /** * Returns a new array containing only the elements that match the filter predicate within the specified range in the input array. * An empty array is returned if the input array/range is empty. * * @param a the array of bytes to be filtered * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param filter the predicate used to filter the array * @return a a new array containing only the elements that match the filter predicate within the specified range * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #filter(int[], IntPredicate) */ public static byte[] filter(final byte[] a, final int fromIndex, final int toIndex, final BytePredicate filter) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_BYTE_ARRAY; } byte[] result = new byte[(toIndex - fromIndex) / 2]; int len = result.length; int count = 0; for (int i = fromIndex; i < toIndex; i++) { if (filter.test(a[i])) { if (count == len) { result = copyOf(result, toIndex - fromIndex); len = result.length; } result[count++] = a[i]; } } return result.length == count ? result : copyOfRange(result, 0, count); } /** * Returns a new array containing only the elements that match the filter predicate. * An empty array is returned if the input array is empty. * * @param a the array of short values to be filtered * @param filter the predicate used to filter the array * @return a new array containing only the elements that match the filter predicate * @see #filter(int[], IntPredicate) */ public static short[] filter(final short[] a, final ShortPredicate filter) { if (isEmpty(a)) { return EMPTY_SHORT_ARRAY; } return filter(a, 0, a.length, filter); } /** * Returns a new array containing only the elements that match the filter predicate within the specified range in the input array. * An empty array is returned if the input array/range is empty. * * @param a the array of short values to be filtered * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param filter the predicate used to filter the array * @return a a new array containing only the elements that match the filter predicate within the specified range * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #filter(int[], IntPredicate) */ public static short[] filter(final short[] a, final int fromIndex, final int toIndex, final ShortPredicate filter) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_SHORT_ARRAY; } short[] result = new short[(toIndex - fromIndex) / 2]; int len = result.length; int count = 0; for (int i = fromIndex; i < toIndex; i++) { if (filter.test(a[i])) { if (count == len) { result = copyOf(result, toIndex - fromIndex); len = result.length; } result[count++] = a[i]; } } return result.length == count ? result : copyOfRange(result, 0, count); } /** * Returns a new array containing only the elements that match the filter predicate. * An empty array is returned if the input array is empty. * * @param a the array of int values to be filtered * @param filter the predicate used to filter the array * @return a new array containing only the elements that match the filter predicate * @see #filter(int[], IntPredicate) */ public static int[] filter(final int[] a, final IntPredicate filter) { if (isEmpty(a)) { return EMPTY_INT_ARRAY; } return filter(a, 0, a.length, filter); } /** * Returns a new array containing only the elements that match the filter predicate within the specified range in the input array. * An empty array is returned if the input array/range is empty. * * @param a the array of int values to be filtered * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param filter the predicate used to filter the array * @return a a new array containing only the elements that match the filter predicate within the specified range * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #filter(int[], IntPredicate) */ public static int[] filter(final int[] a, final int fromIndex, final int toIndex, final IntPredicate filter) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_INT_ARRAY; } int[] result = new int[(toIndex - fromIndex) / 2]; int len = result.length; int count = 0; for (int i = fromIndex; i < toIndex; i++) { if (filter.test(a[i])) { if (count == len) { result = copyOf(result, toIndex - fromIndex); len = result.length; } result[count++] = a[i]; } } return result.length == count ? result : copyOfRange(result, 0, count); } /** * Returns a new array containing only the elements that match the filter predicate. * An empty array is returned if the input array is empty. * * @param a the array of long values to be filtered * @param filter the predicate used to filter the array * @return a new array containing only the elements that match the filter predicate * @see #filter(int[], IntPredicate) */ public static long[] filter(final long[] a, final LongPredicate filter) { if (isEmpty(a)) { return EMPTY_LONG_ARRAY; } return filter(a, 0, a.length, filter); } /** * Returns a new array containing only the elements that match the filter predicate within the specified range in the input array. * An empty array is returned if the input array/range is empty. * * @param a the array of long values to be filtered * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param filter the predicate used to filter the array * @return a a new array containing only the elements that match the filter predicate within the specified range * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #filter(int[], IntPredicate) */ public static long[] filter(final long[] a, final int fromIndex, final int toIndex, final LongPredicate filter) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_LONG_ARRAY; } long[] result = new long[(toIndex - fromIndex) / 2]; int len = result.length; int count = 0; for (int i = fromIndex; i < toIndex; i++) { if (filter.test(a[i])) { if (count == len) { result = copyOf(result, toIndex - fromIndex); len = result.length; } result[count++] = a[i]; } } return result.length == count ? result : copyOfRange(result, 0, count); } /** * Returns a new array containing only the elements that match the filter predicate. * An empty array is returned if the input array is empty. * * @param a the array of float values to be filtered * @param filter the predicate used to filter the array * @return a new array containing only the elements that match the filter predicate * @see #filter(int[], IntPredicate) */ public static float[] filter(final float[] a, final FloatPredicate filter) { if (isEmpty(a)) { return EMPTY_FLOAT_ARRAY; } return filter(a, 0, a.length, filter); } /** * Returns a new array containing only the elements that match the filter predicate within the specified range in the input array. * An empty array is returned if the input array/range is empty. * * @param a the array of float values to be filtered * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param filter the predicate used to filter the array * @return a a new array containing only the elements that match the filter predicate within the specified range * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #filter(int[], IntPredicate) */ public static float[] filter(final float[] a, final int fromIndex, final int toIndex, final FloatPredicate filter) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_FLOAT_ARRAY; } float[] result = new float[(toIndex - fromIndex) / 2]; int len = result.length; int count = 0; for (int i = fromIndex; i < toIndex; i++) { if (filter.test(a[i])) { if (count == len) { result = copyOf(result, toIndex - fromIndex); len = result.length; } result[count++] = a[i]; } } return result.length == count ? result : copyOfRange(result, 0, count); } /** * Returns a new array containing only the elements that match the filter predicate. * An empty array is returned if the input array is empty. * * @param a the array of double values to be filtered * @param filter the predicate used to filter the array * @return a new array containing only the elements that match the filter predicate * @see #filter(int[], IntPredicate) */ public static double[] filter(final double[] a, final DoublePredicate filter) { if (isEmpty(a)) { return EMPTY_DOUBLE_ARRAY; } return filter(a, 0, a.length, filter); } /** * Returns a new array containing only the elements that match the filter predicate within the specified range in the input array. * An empty array is returned if the input array/range is empty. * * @param a the array of double values to be filtered * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param filter the predicate used to filter the array * @return a a new array containing only the elements that match the filter predicate within the specified range * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #filter(int[], IntPredicate) */ public static double[] filter(final double[] a, final int fromIndex, final int toIndex, final DoublePredicate filter) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_DOUBLE_ARRAY; } double[] result = new double[(toIndex - fromIndex) / 2]; int len = result.length; int count = 0; for (int i = fromIndex; i < toIndex; i++) { if (filter.test(a[i])) { if (count == len) { result = copyOf(result, toIndex - fromIndex); len = result.length; } result[count++] = a[i]; } } return result.length == count ? result : copyOfRange(result, 0, count); } /** * Returns a new list containing only the elements that match the filter predicate. * An empty list is returned if the input array is empty. * * @param the type of the elements in the array * @param a the array of values to be filtered * @param filter the predicate used to filter the array * @return a new list containing only the elements that match the filter predicate * @see #filter(int[], IntPredicate) */ public static List filter(final T[] a, final Predicate filter) { if (isEmpty(a)) { return new ArrayList<>(); } return filter(a, filter, Factory.ofList()); } /** * Returns a new collection containing only the elements that match the filter predicate. * An empty collection is returned if the input array is empty. * The collection is created by the provided supplier function. * * @param the type of the elements in the array * @param a the array of values to be filtered * @param filter the predicate used to filter the array * @param supplier the supplier function that provides a new collection to store the filtered elements * @return a new collection containing only the elements that match the filter predicate * @see #filter(int[], IntPredicate) */ public static > C filter(final T[] a, final Predicate filter, final IntFunction supplier) throws IndexOutOfBoundsException { if (isEmpty(a)) { return supplier.apply(0); } return filter(a, 0, a.length, filter, supplier); } /** * Returns a new list containing only the elements that match the filter predicate within the specified range in the input array. * An empty list is returned if the input array/range is empty. * * @param the type of the elements in the array * @param a the array of values to be filtered * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param filter the predicate used to filter the array * @return a new list containing only the elements that match the filter predicate within the specified range * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #filter(int[], IntPredicate) */ public static List filter(final T[] a, final int fromIndex, final int toIndex, final Predicate filter) throws IndexOutOfBoundsException { return filter(a, fromIndex, toIndex, filter, Factory.ofList()); } /** * Returns a new collection containing only the elements that match the filter predicate within the specified range in the input array. * An empty collection is returned if the input array/range is empty. * The collection is created by the provided supplier function. * * @param the type of the elements in the array * @param a the array of values to be filtered * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param filter the predicate used to filter the array * @param supplier the supplier function that provides a new collection to store the filtered elements * @return a new collection containing only the elements that match the filter predicate within the specified range * @throws IndexOutOfBoundsException if the specified range is out of the array's bounds. * @see #filter(int[], IntPredicate) */ public static > C filter(final T[] a, final int fromIndex, final int toIndex, final Predicate filter, final IntFunction supplier) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return supplier.apply(0); } final C result = supplier.apply(min(9, (toIndex - fromIndex))); for (int i = fromIndex; i < toIndex; i++) { if (filter.test(a[i])) { result.add(a[i]); } } return result; } /** * Returns a new list containing only the elements that match the filter predicate within the specified range in the input collection. * An empty list is returned if the input collection/range is empty. * * @param the type of the elements in the collection * @param c the collection of values to be filtered * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param filter the predicate used to filter the collection * @return a new list containing only the elements that match the filter predicate within the specified range * @throws IndexOutOfBoundsException if the specified range is out of the collection's bounds. * @see #filter(int[], IntPredicate) */ public static List filter(final Collection c, final int fromIndex, final int toIndex, final Predicate filter) throws IndexOutOfBoundsException { return filter(c, fromIndex, toIndex, filter, Factory.ofList()); } /** * Returns a new collection containing only the elements that match the filter predicate within the specified range in the input collection. * An empty collection is returned if the input collection/range is empty. * The collection is created by the provided supplier function. * * @param the type of the elements in the collection * @param c the collection of values to be filtered * @param fromIndex The start index (inclusive) of the range. * @param toIndex The end index (exclusive) of the range. * @param filter the predicate used to filter the collection * @param supplier the supplier function that provides a new collection to store the filtered elements * @return a new collection containing only the elements that match the filter predicate within the specified range * @throws IndexOutOfBoundsException if the specified range is out of the collection's bounds. * @see #filter(int[], IntPredicate) */ public static > C filter(final Collection c, final int fromIndex, final int toIndex, final Predicate filter, final IntFunction supplier) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); // NOSONAR if (isEmpty(c) || fromIndex == toIndex) { return supplier.apply(0); } final C result = supplier.apply(min(9, (toIndex - fromIndex))); if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; T e = null; for (int i = fromIndex; i < toIndex; i++) { e = list.get(i); if (filter.test(e)) { result.add(e); } } } else { int idx = 0; for (final T e : c) { if (idx++ < fromIndex) { continue; } if (filter.test(e)) { result.add(e); } if (idx >= toIndex) { break; } } } return result; } /** * Returns a new list containing only the elements that match the filter predicate. * An empty list is returned if the input collection is empty. * * @param the type of the elements in the iterable * @param c the iterable of values to be filtered * @param filter the predicate used to filter the iterable * @return a new list containing only the elements that match the filter predicate * @see #filter(int[], IntPredicate) */ public static List filter(final Iterable c, final Predicate filter) { return filter(c, filter, Factory.ofList()); } /** * Returns a new collection containing only the elements that match the filter predicate. * An empty collection is returned if the input collection is empty. * The collection is created by the provided supplier function. * * @param the type of the elements in the iterable * @param c the iterable of values to be filtered * @param filter the predicate used to filter the iterable * @param supplier the supplier function that provides a new collection to store the filtered elements * @return a new collection containing only the elements that match the filter predicate * @see #filter(int[], IntPredicate) */ public static > C filter(final Iterable c, final Predicate filter, final IntFunction supplier) { if (isEmptyCollection(c)) { return supplier.apply(0); } final C result = supplier.apply(getMinSize(c)); for (final T e : c) { if (filter.test(e)) { result.add(e); } } return result; } /** * Returns a new list containing only the elements that match the filter predicate. * An empty list is returned if the input iterator is empty. * * @param the type of the elements in the iterator * @param iter the iterator of values to be filtered * @param filter the predicate used to filter the iterator * @return a new list containing only the elements that match the filter predicate * @see #filter(int[], IntPredicate) */ public static List filter(final Iterator iter, final Predicate filter) { return filter(iter, filter, Factory.ofList()); } /** * Returns a new collection containing only the elements that match the filter predicate. * An empty collection is returned if the input iterator is empty. * The collection is created by the provided supplier function. * * @param the type of the elements in the iterator * @param iter the iterator of values to be filtered * @param filter the predicate used to filter the iterator * @param supplier the supplier function that provides a new collection to store the filtered elements * @return a new collection containing only the elements that match the filter predicate * @see #filter(int[], IntPredicate) */ public static > C filter(final Iterator iter, final Predicate filter, final IntFunction supplier) { if (iter == null) { return supplier.apply(0); } final C result = supplier.apply(9); T e = null; while (iter.hasNext()) { e = iter.next(); if (filter.test(e)) { result.add(e); } } return result; } /** * Transforms the elements of the specified array to boolean values using the specified {@code ToBooleanFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the array * @param a the array of values to be mapped * @param mapper the function used to map the elements to boolean values * @return a new boolean array containing the mapped values, or an empty boolean array if the input array is {@code null} or empty * @see #mapToInt(Object[], ToIntFunction) */ public static boolean[] mapToBoolean(final T[] a, final ToBooleanFunction mapper) { if (isEmpty(a)) { return EMPTY_BOOLEAN_ARRAY; } return mapToBoolean(a, 0, a.length, mapper); } /** * Transforms the elements within the specified range in the input array to boolean values using the specified {@code ToBooleanFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the array * @param a the array of values to be mapped * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper the function used to map the elements to boolean values * @return a new boolean array containing the mapped values, or an empty boolean array if the input array/range is {@code null} or empty * @throws IndexOutOfBoundsException the specified range is out of the array's bounds. * @see #mapToInt(Object[], ToIntFunction) */ public static boolean[] mapToBoolean(final T[] a, final int fromIndex, final int toIndex, final ToBooleanFunction mapper) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_BOOLEAN_ARRAY; } final boolean[] result = new boolean[toIndex - fromIndex]; for (int i = fromIndex; i < toIndex; i++) { result[i - fromIndex] = mapper.applyAsBoolean(a[i]); } return result; } /** * Transforms the elements of the specified collection to boolean values using the specified {@code ToBooleanFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the collection * @param c the collection of values to be mapped * @param mapper the function used to map the elements to boolean values * @return a new boolean array containing the mapped values, or an empty boolean collection if the input array is {@code null} or empty * @see #mapToInt(Object[], ToIntFunction) */ public static boolean[] mapToBoolean(final Collection c, final ToBooleanFunction mapper) { if (isEmpty(c)) { return EMPTY_BOOLEAN_ARRAY; } return mapToBoolean(c, 0, c.size(), mapper); } /** * Transforms the elements within the specified range in the input collection to boolean values using the specified {@code ToBooleanFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the collection * @param c the collection of values to be mapped * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper the function used to map the elements to boolean values * @return a new boolean array containing the mapped values, or an empty boolean array if the input collection/range is {@code null} or empty * @throws IndexOutOfBoundsException the specified range is out of the collection's bounds. * @see #mapToInt(Object[], ToIntFunction) */ public static boolean[] mapToBoolean(final Collection c, final int fromIndex, final int toIndex, final ToBooleanFunction mapper) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); if ((isEmpty(c) && fromIndex == 0 && toIndex == 0) || fromIndex == toIndex) { return EMPTY_BOOLEAN_ARRAY; } final boolean[] result = new boolean[toIndex - fromIndex]; if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; for (int i = fromIndex; i < toIndex; i++) { result[i - fromIndex] = mapper.applyAsBoolean(list.get(i)); } } else { int idx = 0; for (final T e : c) { if (idx++ < fromIndex) { continue; } result[idx - fromIndex] = mapper.applyAsBoolean(e); if (idx >= toIndex) { break; } } } return result; } /** * Transforms the elements of the specified array to char values using the specified {@code ToCharFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the array * @param a the array of values to be mapped * @param mapper the function used to map the elements to char values * @return a new char array containing the mapped values, or an empty char array if the input array is {@code null} or empty * @see #mapToInt(Object[], ToIntFunction) */ public static char[] mapToChar(final T[] a, final ToCharFunction mapper) { if (isEmpty(a)) { return EMPTY_CHAR_ARRAY; } return mapToChar(a, 0, a.length, mapper); } /** * Transforms the elements within the specified range in the input array to char values using the specified {@code ToCharFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the array * @param a the array of values to be mapped * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper the function used to map the elements to char values * @return a new char array containing the mapped values, or an empty char array if the input array/range is {@code null} or empty * @throws IndexOutOfBoundsException the specified range is out of the array's bounds. * @see #mapToInt(Object[], ToIntFunction) */ public static char[] mapToChar(final T[] a, final int fromIndex, final int toIndex, final ToCharFunction mapper) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_CHAR_ARRAY; } final char[] result = new char[toIndex - fromIndex]; for (int i = fromIndex; i < toIndex; i++) { result[i - fromIndex] = mapper.applyAsChar(a[i]); } return result; } /** * Transforms the elements of the specified collection to char values using the specified {@code ToCharFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the collection * @param c the collection of values to be mapped * @param mapper the function used to map the elements to char values * @return a new char array containing the mapped values, or an empty char collection if the input array is {@code null} or empty * @see #mapToInt(Object[], ToIntFunction) */ public static char[] mapToChar(final Collection c, final ToCharFunction mapper) { if (isEmpty(c)) { return EMPTY_CHAR_ARRAY; } return mapToChar(c, 0, c.size(), mapper); } /** * Transforms the elements within the specified range in the input collection to char values using the specified {@code ToCharFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the collection * @param c the collection of values to be mapped * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper the function used to map the elements to char values * @return a new char array containing the mapped values, or an empty char array if the input collection/range is {@code null} or empty * @throws IndexOutOfBoundsException the specified range is out of the collection's bounds. * @see #mapToInt(Object[], ToIntFunction) */ public static char[] mapToChar(final Collection c, final int fromIndex, final int toIndex, final ToCharFunction mapper) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); if ((isEmpty(c) && fromIndex == 0 && toIndex == 0) || fromIndex == toIndex) { return EMPTY_CHAR_ARRAY; } final char[] result = new char[toIndex - fromIndex]; if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; for (int i = fromIndex; i < toIndex; i++) { result[i - fromIndex] = mapper.applyAsChar(list.get(i)); } } else { int idx = 0; for (final T e : c) { if (idx++ < fromIndex) { continue; } result[idx - fromIndex] = mapper.applyAsChar(e); if (idx >= toIndex) { break; } } } return result; } /** * Transforms the elements of the specified array to byte values using the specified {@code ToByteFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the array * @param a the array of values to be mapped * @param mapper the function used to map the elements to byte values * @return a new byte array containing the mapped values, or an empty byte array if the input array is {@code null} or empty * @see #mapToInt(Object[], ToIntFunction) */ public static byte[] mapToByte(final T[] a, final ToByteFunction mapper) { if (isEmpty(a)) { return EMPTY_BYTE_ARRAY; } return mapToByte(a, 0, a.length, mapper); } /** * Transforms the elements within the specified range in the input array to byte values using the specified {@code ToByteFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the array * @param a the array of values to be mapped * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper the function used to map the elements to byte values * @return a new byte array containing the mapped values, or an empty byte array if the input array/range is {@code null} or empty * @throws IndexOutOfBoundsException the specified range is out of the array's bounds. * @see #mapToInt(Object[], ToIntFunction) */ public static byte[] mapToByte(final T[] a, final int fromIndex, final int toIndex, final ToByteFunction mapper) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_BYTE_ARRAY; } final byte[] result = new byte[toIndex - fromIndex]; for (int i = fromIndex; i < toIndex; i++) { result[i - fromIndex] = mapper.applyAsByte(a[i]); } return result; } /** * Transforms the elements of the specified collection to byte values using the specified {@code ToByteFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the collection * @param c the collection of values to be mapped * @param mapper the function used to map the elements to byte values * @return a new byte array containing the mapped values, or an empty byte collection if the input array is {@code null} or empty * @see #mapToInt(Object[], ToIntFunction) */ public static byte[] mapToByte(final Collection c, final ToByteFunction mapper) { if (isEmpty(c)) { return EMPTY_BYTE_ARRAY; } return mapToByte(c, 0, c.size(), mapper); } /** * Transforms the elements within the specified range in the input collection to byte values using the specified {@code ToByteFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the collection * @param c the collection of values to be mapped * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper the function used to map the elements to byte values * @return a new byte array containing the mapped values, or an empty byte array if the input collection/range is {@code null} or empty * @throws IndexOutOfBoundsException the specified range is out of the collection's bounds. * @see #mapToInt(Object[], ToIntFunction) */ public static byte[] mapToByte(final Collection c, final int fromIndex, final int toIndex, final ToByteFunction mapper) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); if ((isEmpty(c) && fromIndex == 0 && toIndex == 0) || fromIndex == toIndex) { return EMPTY_BYTE_ARRAY; } final byte[] result = new byte[toIndex - fromIndex]; if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; for (int i = fromIndex; i < toIndex; i++) { result[i - fromIndex] = mapper.applyAsByte(list.get(i)); } } else { int idx = 0; for (final T e : c) { if (idx++ < fromIndex) { continue; } result[idx - fromIndex] = mapper.applyAsByte(e); if (idx >= toIndex) { break; } } } return result; } /** * Transforms the elements of the specified array to short values using the specified {@code ToShortFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the array * @param a the array of values to be mapped * @param mapper the function used to map the elements to short values * @return a new short array containing the mapped values, or an empty short array if the input array is {@code null} or empty * @see #mapToInt(Object[], ToIntFunction) */ public static short[] mapToShort(final T[] a, final ToShortFunction mapper) { if (isEmpty(a)) { return EMPTY_SHORT_ARRAY; } return mapToShort(a, 0, a.length, mapper); } /** * Transforms the elements within the specified range in the input array to short values using the specified {@code ToShortFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the array * @param a the array of values to be mapped * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper the function used to map the elements to short values * @return a new short array containing the mapped values, or an empty short array if the input array/range is {@code null} or empty * @throws IndexOutOfBoundsException the specified range is out of the array's bounds. * @see #mapToInt(Object[], ToIntFunction) */ public static short[] mapToShort(final T[] a, final int fromIndex, final int toIndex, final ToShortFunction mapper) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_SHORT_ARRAY; } final short[] result = new short[toIndex - fromIndex]; for (int i = fromIndex; i < toIndex; i++) { result[i - fromIndex] = mapper.applyAsShort(a[i]); } return result; } /** * Transforms the elements of the specified collection to short values using the specified {@code ToShortFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the collection * @param c the collection of values to be mapped * @param mapper the function used to map the elements to short values * @return a new short array containing the mapped values, or an empty short collection if the input array is {@code null} or empty * @see #mapToInt(Object[], ToIntFunction) */ public static short[] mapToShort(final Collection c, final ToShortFunction mapper) { if (isEmpty(c)) { return EMPTY_SHORT_ARRAY; } return mapToShort(c, 0, c.size(), mapper); } /** * Transforms the elements within the specified range in the input collection to short values using the specified {@code ToShortFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the collection * @param c the collection of values to be mapped * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper the function used to map the elements to short values * @return a new short array containing the mapped values, or an empty short array if the input collection/range is {@code null} or empty * @throws IndexOutOfBoundsException the specified range is out of the collection's bounds. * @see #mapToInt(Object[], ToIntFunction) */ public static short[] mapToShort(final Collection c, final int fromIndex, final int toIndex, final ToShortFunction mapper) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); if ((isEmpty(c) && fromIndex == 0 && toIndex == 0) || fromIndex == toIndex) { return EMPTY_SHORT_ARRAY; } final short[] result = new short[toIndex - fromIndex]; if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; for (int i = fromIndex; i < toIndex; i++) { result[i - fromIndex] = mapper.applyAsShort(list.get(i)); } } else { int idx = 0; for (final T e : c) { if (idx++ < fromIndex) { continue; } result[idx - fromIndex] = mapper.applyAsShort(e); if (idx >= toIndex) { break; } } } return result; } /** * Transforms the elements of the specified array to int values using the specified {@code ToIntFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the array * @param a the array of values to be mapped * @param mapper the function used to map the elements to int values * @return a new int array containing the mapped values, or an empty int array if the input array is {@code null} or empty */ public static int[] mapToInt(final T[] a, final ToIntFunction mapper) { if (isEmpty(a)) { return EMPTY_INT_ARRAY; } return mapToInt(a, 0, a.length, mapper); } /** * Transforms the elements within the specified range in the input array to int values using the specified {@code ToIntFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the array * @param a the array of values to be mapped * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper the function used to map the elements to int values * @return a new int array containing the mapped values, or an empty int array if the input array/range is {@code null} or empty * @throws IndexOutOfBoundsException the specified range is out of the array's bounds. * @see #mapToInt(Object[], ToIntFunction) */ public static int[] mapToInt(final T[] a, final int fromIndex, final int toIndex, final ToIntFunction mapper) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_INT_ARRAY; } final int[] result = new int[toIndex - fromIndex]; for (int i = fromIndex; i < toIndex; i++) { result[i - fromIndex] = mapper.applyAsInt(a[i]); } return result; } /** * Transforms the elements of the specified collection to int values using the specified {@code ToIntFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the collection * @param c the collection of values to be mapped * @param mapper the function used to map the elements to int values * @return a new int array containing the mapped values, or an empty int collection if the input array is {@code null} or empty * @see #mapToInt(Object[], ToIntFunction) */ public static int[] mapToInt(final Collection c, final ToIntFunction mapper) { if (isEmpty(c)) { return EMPTY_INT_ARRAY; } return mapToInt(c, 0, c.size(), mapper); } /** * Transforms the elements within the specified range in the input collection to int values using the specified {@code ToIntFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the collection * @param c the collection of values to be mapped * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper the function used to map the elements to int values * @return a new int array containing the mapped values, or an empty int array if the input collection/range is {@code null} or empty * @throws IndexOutOfBoundsException the specified range is out of the collection's bounds. * @see #mapToInt(Object[], ToIntFunction) */ public static int[] mapToInt(final Collection c, final int fromIndex, final int toIndex, final ToIntFunction mapper) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); if ((isEmpty(c) && fromIndex == 0 && toIndex == 0) || fromIndex == toIndex) { return EMPTY_INT_ARRAY; } final int[] result = new int[toIndex - fromIndex]; if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; for (int i = fromIndex; i < toIndex; i++) { result[i - fromIndex] = mapper.applyAsInt(list.get(i)); } } else { int idx = 0; for (final T e : c) { if (idx++ < fromIndex) { continue; } result[idx - fromIndex] = mapper.applyAsInt(e); if (idx >= toIndex) { break; } } } return result; } /** * Transforms the long values in the specified array to int values using the specified {@code LongToIntFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param a the array of long values to be mapped * @param mapper the function used to map the long values to int values * @return a new int array containing the mapped values, or an empty int array if the input array is {@code null} or empty */ @Beta public static int[] mapToInt(final long[] a, final LongToIntFunction mapper) { if (a == null) { return EMPTY_INT_ARRAY; } final int len = len(a); final int[] result = new int[len]; for (int i = 0; i < len; i++) { result[i] = mapper.applyAsInt(a[i]); } return result; } /** * Transforms the double values in the specified array to int values using the specified {@code DoubleToIntFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param a the array of double values to be mapped * @param mapper the function used to map the double values to int values * @return a new int array containing the mapped values, or an empty int array if the input array is {@code null} or empty */ @Beta public static int[] mapToInt(final double[] a, final DoubleToIntFunction mapper) { if (a == null) { return EMPTY_INT_ARRAY; } final int len = len(a); final int[] result = new int[len]; for (int i = 0; i < len; i++) { result[i] = mapper.applyAsInt(a[i]); } return result; } /** * Transforms the elements of the specified array to long values using the specified {@code ToLongFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the array * @param a the array of values to be mapped * @param mapper the function used to map the elements to long values * @return a new long array containing the mapped values, or an empty long array if the input array is {@code null} or empty */ public static long[] mapToLong(final T[] a, final ToLongFunction mapper) { if (isEmpty(a)) { return EMPTY_LONG_ARRAY; } return mapToLong(a, 0, a.length, mapper); } /** * Transforms the elements within the specified range in the input array to long values using the specified {@code ToLongFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the array * @param a the array of values to be mapped * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper the function used to map the elements to long values * @return a new long array containing the mapped values, or an empty long array if the input array/range is {@code null} or empty * @throws IndexOutOfBoundsException the specified range is out of the array's bounds. * @see #mapToInt(Object[], ToIntFunction) */ public static long[] mapToLong(final T[] a, final int fromIndex, final int toIndex, final ToLongFunction mapper) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_LONG_ARRAY; } final long[] result = new long[toIndex - fromIndex]; for (int i = fromIndex; i < toIndex; i++) { result[i - fromIndex] = mapper.applyAsLong(a[i]); } return result; } /** * Transforms the elements of the specified collection to long values using the specified {@code ToLongFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the collection * @param c the collection of values to be mapped * @param mapper the function used to map the elements to long values * @return a new long array containing the mapped values, or an empty long collection if the input array is {@code null} or empty * @see #mapToInt(Object[], ToIntFunction) */ public static long[] mapToLong(final Collection c, final ToLongFunction mapper) { if (isEmpty(c)) { return EMPTY_LONG_ARRAY; } return mapToLong(c, 0, c.size(), mapper); } /** * Transforms the elements within the specified range in the input collection to long values using the specified {@code ToLongFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the collection * @param c the collection of values to be mapped * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper the function used to map the elements to long values * @return a new long array containing the mapped values, or an empty long array if the input collection/range is {@code null} or empty * @throws IndexOutOfBoundsException the specified range is out of the collection's bounds. * @see #mapToInt(Object[], ToIntFunction) */ public static long[] mapToLong(final Collection c, final int fromIndex, final int toIndex, final ToLongFunction mapper) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); if ((isEmpty(c) && fromIndex == 0 && toIndex == 0) || fromIndex == toIndex) { return EMPTY_LONG_ARRAY; } final long[] result = new long[toIndex - fromIndex]; if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; for (int i = fromIndex; i < toIndex; i++) { result[i - fromIndex] = mapper.applyAsLong(list.get(i)); } } else { int idx = 0; for (final T e : c) { if (idx++ < fromIndex) { continue; } result[idx - fromIndex] = mapper.applyAsLong(e); if (idx >= toIndex) { break; } } } return result; } /** * Transforms the int values in the specified array to long values using the specified {@code IntToLongFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param a the array of int values to be mapped * @param mapper the function used to map the int values to long values * @return a new long array containing the mapped values, or an empty long array if the input array is {@code null} or empty */ @Beta public static long[] mapToLong(final int[] a, final IntToLongFunction mapper) { if (a == null) { return EMPTY_LONG_ARRAY; } final int len = len(a); final long[] result = new long[len]; for (int i = 0; i < len; i++) { result[i] = mapper.applyAsLong(a[i]); } return result; } /** * Transforms the double values in the specified array to long values using the specified {@code DoubleToLongFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param a the array of double values to be mapped * @param mapper the function used to map the double values to long values * @return a new long array containing the mapped values, or an empty long array if the input array is {@code null} or empty */ @Beta public static long[] mapToLong(final double[] a, final DoubleToLongFunction mapper) { if (a == null) { return EMPTY_LONG_ARRAY; } final int len = len(a); final long[] result = new long[len]; for (int i = 0; i < len; i++) { result[i] = mapper.applyAsLong(a[i]); } return result; } /** * Transforms the elements of the specified array to float values using the specified {@code ToFloatFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the array * @param a the array of values to be mapped * @param mapper the function used to map the elements to float values * @return a new float array containing the mapped values, or an empty float array if the input array is {@code null} or empty */ public static float[] mapToFloat(final T[] a, final ToFloatFunction mapper) { if (isEmpty(a)) { return EMPTY_FLOAT_ARRAY; } return mapToFloat(a, 0, a.length, mapper); } /** * Transforms the elements within the specified range in the input array to float values using the specified {@code ToFloatFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the array * @param a the array of values to be mapped * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper the function used to map the elements to float values * @return a new float array containing the mapped values, or an empty float array if the input array/range is {@code null} or empty * @throws IndexOutOfBoundsException the specified range is out of the array's bounds. * @see #mapToInt(Object[], ToIntFunction) */ public static float[] mapToFloat(final T[] a, final int fromIndex, final int toIndex, final ToFloatFunction mapper) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_FLOAT_ARRAY; } final float[] result = new float[toIndex - fromIndex]; for (int i = fromIndex; i < toIndex; i++) { result[i - fromIndex] = mapper.applyAsFloat(a[i]); } return result; } /** * Transforms the elements of the specified collection to float values using the specified {@code ToFloatFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the collection * @param c the collection of values to be mapped * @param mapper the function used to map the elements to float values * @return a new float array containing the mapped values, or an empty float collection if the input array is {@code null} or empty * @see #mapToInt(Object[], ToIntFunction) */ public static float[] mapToFloat(final Collection c, final ToFloatFunction mapper) { if (isEmpty(c)) { return EMPTY_FLOAT_ARRAY; } return mapToFloat(c, 0, c.size(), mapper); } /** * Transforms the elements within the specified range in the input collection to float values using the specified {@code ToFloatFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the collection * @param c the collection of values to be mapped * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper the function used to map the elements to float values * @return a new float array containing the mapped values, or an empty float array if the input collection/range is {@code null} or empty * @throws IndexOutOfBoundsException the specified range is out of the collection's bounds. * @see #mapToInt(Object[], ToIntFunction) */ public static float[] mapToFloat(final Collection c, final int fromIndex, final int toIndex, final ToFloatFunction mapper) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); if ((isEmpty(c) && fromIndex == 0 && toIndex == 0) || fromIndex == toIndex) { return EMPTY_FLOAT_ARRAY; } final float[] result = new float[toIndex - fromIndex]; if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; for (int i = fromIndex; i < toIndex; i++) { result[i - fromIndex] = mapper.applyAsFloat(list.get(i)); } } else { int idx = 0; for (final T e : c) { if (idx++ < fromIndex) { continue; } result[idx - fromIndex] = mapper.applyAsFloat(e); if (idx >= toIndex) { break; } } } return result; } /** * Transforms the elements of the specified array to double values using the specified {@code ToDoubleFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the array * @param a the array of values to be mapped * @param mapper the function used to map the elements to double values * @return a new double array containing the mapped values, or an empty double array if the input array is {@code null} or empty */ public static double[] mapToDouble(final T[] a, final ToDoubleFunction mapper) { if (isEmpty(a)) { return EMPTY_DOUBLE_ARRAY; } return mapToDouble(a, 0, a.length, mapper); } /** * Transforms the elements within the specified range in the input array to double values using the specified {@code ToDoubleFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the array * @param a the array of values to be mapped * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper the function used to map the elements to double values * @return a new double array containing the mapped values, or an empty double array if the input array/range is {@code null} or empty * @throws IndexOutOfBoundsException the specified range is out of the array's bounds. * @see #mapToInt(Object[], ToIntFunction) */ public static double[] mapToDouble(final T[] a, final int fromIndex, final int toIndex, final ToDoubleFunction mapper) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return EMPTY_DOUBLE_ARRAY; } final double[] result = new double[toIndex - fromIndex]; for (int i = fromIndex; i < toIndex; i++) { result[i - fromIndex] = mapper.applyAsDouble(a[i]); } return result; } /** * Transforms the elements of the specified collection to double values using the specified {@code ToDoubleFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the collection * @param c the collection of values to be mapped * @param mapper the function used to map the elements to double values * @return a new double array containing the mapped values, or an empty double collection if the input array is {@code null} or empty * @see #mapToInt(Object[], ToIntFunction) */ public static double[] mapToDouble(final Collection c, final ToDoubleFunction mapper) { if (isEmpty(c)) { return EMPTY_DOUBLE_ARRAY; } return mapToDouble(c, 0, c.size(), mapper); } /** * Transforms the elements within the specified range in the input collection to double values using the specified {@code ToDoubleFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the collection * @param c the collection of values to be mapped * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper the function used to map the elements to double values * @return a new double array containing the mapped values, or an empty double array if the input collection/range is {@code null} or empty * @throws IndexOutOfBoundsException the specified range is out of the collection's bounds. * @see #mapToInt(Object[], ToIntFunction) */ public static double[] mapToDouble(final Collection c, final int fromIndex, final int toIndex, final ToDoubleFunction mapper) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); if ((isEmpty(c) && fromIndex == 0 && toIndex == 0) || fromIndex == toIndex) { return EMPTY_DOUBLE_ARRAY; } final double[] result = new double[toIndex - fromIndex]; if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; for (int i = fromIndex; i < toIndex; i++) { result[i - fromIndex] = mapper.applyAsDouble(list.get(i)); } } else { int idx = 0; for (final T e : c) { if (idx++ < fromIndex) { continue; } result[idx - fromIndex] = mapper.applyAsDouble(e); if (idx >= toIndex) { break; } } } return result; } /** * Transforms the int values in the specified array to double values using the specified {@code IntToDoubleFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param a the array of int values to be mapped * @param mapper the function used to map the int values to double values * @return a new double array containing the mapped values, or an empty double array if the input array is {@code null} or empty */ @Beta public static double[] mapToDouble(final int[] a, final IntToDoubleFunction mapper) { if (a == null) { return EMPTY_DOUBLE_ARRAY; } final int len = len(a); final double[] result = new double[len]; for (int i = 0; i < len; i++) { result[i] = mapper.applyAsDouble(a[i]); } return result; } /** * Transforms the long values in the specified array to double values using the specified {@code IntToDoubleFunction}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param a the array of long values to be mapped * @param mapper the function used to map the long values to double values * @return a new double array containing the mapped values, or an empty double array if the input array is {@code null} or empty */ @Beta public static double[] mapToDouble(final long[] a, final LongToDoubleFunction mapper) { if (a == null) { return EMPTY_DOUBLE_ARRAY; } final int len = len(a); final double[] result = new double[len]; for (int i = 0; i < len; i++) { result[i] = mapper.applyAsDouble(a[i]); } return result; } /** * Transforms the elements in the specified array from type: {code T} to type: {@code R} by applying the specified {@code Function} to each element. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param The type of the elements in the input array. * @param The type of the elements are mapped to. * @param a The input array to be transformed. * @param mapper The function to apply to each element in the input array. * @return A list containing the transformed elements, or an empty list if the input array is {@code null} or empty. */ public static List map(final T[] a, final Function mapper) { if (isEmpty(a)) { return new ArrayList<>(); } return map(a, 0, a.length, mapper); } /** * Transforms the elements in the specified array from type: {code T} to type: {@code R} by applying the specified {@code Function} to each element. *
* The returned collection is created by the specified {@code supplier}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param The type of the elements in the input array. * @param The type of the elements are mapped to. * @param a The input array to be transformed. * @param mapper The function to apply to each element in the input array. * @param supplier The supplier used to create the returned collection. * @return A collection containing the transformed elements, or an empty collection created by the {@code supplier} if the input array/range is {@code null} or empty. */ public static > C map(final T[] a, final Function mapper, final IntFunction supplier) { if (isEmpty(a)) { return supplier.apply(0); } return map(a, 0, a.length, mapper, supplier); } /** * Transforms the elements within the specified range in the input array from type: {code T} to type: {@code R} by applying the specified {@code Function} to each element. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param The type of the elements in the input array. * @param The type of the elements are mapped to. * @param a The input array to be transformed. * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper The function to apply to each element in the input array. * @return A list containing the transformed elements, or an empty list if the input array is {@code null} or empty. * @throws IndexOutOfBoundsException If the specified range is out of the array's bounds. */ public static List map(final T[] a, final int fromIndex, final int toIndex, final Function mapper) throws IndexOutOfBoundsException { return map(a, fromIndex, toIndex, mapper, Factory.ofList()); } /** * Transforms the elements within the specified range in the input array from type: {code T} to type: {@code R} by applying the specified {@code Function} to each element. *
* The returned collection is created by the specified {@code supplier}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param The type of the elements in the input array. * @param The type of the elements are mapped to. * @pram The type of the returned collection * @param a The input array to be transformed. * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper The function to apply to each element in the input array. * @param supplier The supplier used to create the returned collection. * @return A collection containing the transformed elements, or an empty collection created by the {@code supplier} if the input array/range is {@code null} or empty. * @throws IndexOutOfBoundsException If the specified range is out of the array's bounds. */ public static > C map(final T[] a, final int fromIndex, final int toIndex, final Function mapper, final IntFunction supplier) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return supplier.apply(0); } final C result = supplier.apply(toIndex - fromIndex); for (int i = fromIndex; i < toIndex; i++) { result.add(mapper.apply(a[i])); } return result; } /** * Transforms the elements within the specified range in the input collection from type: {code T} to type: {@code R} by applying the specified {@code Function} to each element. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param The type of the elements in the input collection. * @param The type of the elements are mapped to. * @param c The input collection to be transformed. * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper The function to apply to each element in the input collection. * @return A list containing the transformed elements, or an empty list if the input collection is {@code null} or empty. * @throws IndexOutOfBoundsException If the specified range is out of the collection's bounds. */ public static List map(final Collection c, final int fromIndex, final int toIndex, final Function mapper) throws IndexOutOfBoundsException { return map(c, fromIndex, toIndex, mapper, Factory.ofList()); } /** * Transforms the elements within the specified range in the input collection from type: {code T} to type: {@code R} by applying the specified {@code Function} to each element. *
* The returned collection is created by the specified {@code supplier}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param The type of the elements in the input collection. * @param The type of the elements are mapped to. * @param The type of the returned collection * @param c The input collection to be transformed. * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper The function to apply to each element in the input collection. * @param supplier The supplier used to create the returned collection. * @return A collection containing the transformed elements, or an empty collection created by the {@code supplier} if the input collection/range is {@code null} or empty. * @throws IndexOutOfBoundsException If the specified range is out of the collection's bounds. */ public static > C map(final Collection c, final int fromIndex, final int toIndex, final Function mapper, final IntFunction supplier) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); if ((isEmpty(c) && fromIndex == 0 && toIndex == 0) || fromIndex == toIndex) { return supplier.apply(0); } final C result = supplier.apply(toIndex - fromIndex); if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; for (int i = fromIndex; i < toIndex; i++) { result.add(mapper.apply(list.get(i))); } } else { int idx = 0; for (final T e : c) { if (idx++ < fromIndex) { continue; } result.add(mapper.apply(e)); if (idx >= toIndex) { break; } } } return result; } /** * Transforms the elements in the specified iterable from type: {code T} to type: {@code R} by applying the specified {@code Function} to each element. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param The type of the elements in the iterable. * @param The type of the elements are mapped to. * @param c The input iterable to be transformed. * @param mapper The function to apply to each element in the input iterable. * @return A list containing the transformed elements, or an empty list if the input iterable is {@code null} or empty. */ public static List map(final Iterable c, final Function mapper) { return map(c, mapper, Factory.ofList()); } /** * Transforms the elements in the specified iterable from type: {code T} to type: {@code R} by applying the specified {@code Function} to each element. *
* The returned collection is created by the specified {@code supplier}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param The type of the elements in the iterable. * @param The type of the elements are mapped to. * @param The type of the returned collection * @param c The input iterable to be transformed. * @param mapper The function to apply to each element in the input iterable. * @param supplier The supplier used to create the returned collection. * @return A collection containing the transformed elements, or an empty collection created by the {@code supplier} if the input iterable is {@code null} or empty. */ public static > C map(final Iterable c, final Function mapper, final IntFunction supplier) { if (isEmptyCollection(c)) { return supplier.apply(0); } final C result = supplier.apply(getSizeOrDefault(c, 0)); for (final T e : c) { result.add(mapper.apply(e)); } return result; } /** * Transforms the elements in the specified iterator from type: {code T} to type: {@code R} by applying the specified {@code Function} to each element. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param The type of the elements in the iterator. * @param The type of the elements are mapped to. * @param iter The input iterator to be transformed. * @param mapper The function to apply to each element in the input iterator. * @return A list containing the transformed elements, or an empty list if the input iterator is {@code null} or empty. * @see Iterators#map(Iterator, Function) */ public static List map(final Iterator iter, final Function mapper) { return map(iter, mapper, Factory.ofList()); } /** * Transforms the elements in the specified iterator from type: {code T} to type: {@code R} by applying the specified {@code Function} to each element. *
* The returned collection is created by the specified {@code supplier}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param The type of the elements in the iterator. * @param The type of the elements are mapped to. * @param The type of the returned collection * @param iter The input iterable to be transformed. * @param mapper The function to apply to each element in the input iterator. * @param supplier The supplier used to create the returned collection. * @return A collection containing the transformed elements, or an empty collection created by the {@code supplier} if the input iterator is {@code null} or empty. * @see Iterators#map(Iterator, Function) */ public static > C map(final Iterator iter, final Function mapper, final IntFunction supplier) { if (iter == null) { return supplier.apply(0); } final C result = supplier.apply(9); while (iter.hasNext()) { result.add(mapper.apply(iter.next())); } return result; } /** * Transforms the elements in the specified array from type: {code T} to a collection of type: {@code R} by applying the specified {@code Function>} to each element. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param The type of the elements in the input array. * @param The type of the elements are mapped to. * @param a The input array to be transformed. * @param mapper The function to transform each element in the input array to a collection. * @return A list containing the transformed elements, or an empty list if the input array is {@code null} or empty. */ public static List flatMap(final T[] a, final Function> mapper) { if (isEmpty(a)) { return new ArrayList<>(); } return flatMap(a, 0, a.length, mapper); } /** * Transforms the elements in the specified array from type: {code T} to a collection of type: {@code R} by applying the specified {@code Function>} to each element. *
* The returned collection is created by the specified {@code supplier}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param The type of the elements in the input array. * @param The type of the elements are mapped to. * @param a The input array to be transformed. * @param mapper The function to transform each element in the input array to a collection. * @param supplier The supplier used to create the returned collection. * @return A collection containing the transformed elements, or an empty collection created by the {@code supplier} if the input array/range is {@code null} or empty. */ public static > C flatMap(final T[] a, final Function> mapper, final IntFunction supplier) { if (isEmpty(a)) { return supplier.apply(0); } return flatMap(a, 0, a.length, mapper, supplier); } /** * Transforms the elements within the specified range in the input array from type: {code T} to a collection of type: {@code R} by applying the specified {@code Function>} to each element. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param The type of the elements in the input array. * @param The type of the elements are mapped to. * @param a The input array to be transformed. * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper The function to transform each element in the input array to a collection. * @return A list containing the transformed elements, or an empty list if the input array is {@code null} or empty. * @throws IndexOutOfBoundsException If the specified range is out of the array's bounds. */ public static List flatMap(final T[] a, final int fromIndex, final int toIndex, final Function> mapper) { return flatMap(a, fromIndex, toIndex, mapper, Factory.ofList()); } /** * Transforms the elements within the specified range in the input array from type: {code T} to a collection of type: {@code R} by applying the specified {@code Function>} to each element. *
* The returned collection is created by the specified {@code supplier}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param The type of the elements in the input array. * @param The type of the elements are mapped to. * @param The type of the returned collection * @param a The input array to be transformed. * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper The function to transform each element in the input array to a collection. * @param supplier The supplier used to create the returned collection. * @return A collection containing the transformed elements, or an empty collection created by the {@code supplier} if the input array/range is {@code null} or empty. * @throws IndexOutOfBoundsException If the specified range is out of the array's bounds. */ public static > C flatMap(final T[] a, final int fromIndex, final int toIndex, final Function> mapper, final IntFunction supplier) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return supplier.apply(0); } final int len = initSizeForFlatMap(toIndex - fromIndex); final C result = supplier.apply(len); Collection mr = null; for (int i = fromIndex; i < toIndex; i++) { if (notEmpty(mr = mapper.apply(a[i]))) { result.addAll(mr); } } return result; } /** * Transforms the elements within the specified range in the input collection from type: {code T} to a collection of type: {@code R} by applying the specified {@code Function>} to each element. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param The type of the elements in the input collection. * @param The type of the elements are mapped to. * @param c The input collection to be transformed. * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper The function to transform each element in the input collection to a collection. * @return A list containing the transformed elements, or an empty list if the input collection is {@code null} or empty. * @throws IndexOutOfBoundsException If the specified range is out of the collection's bounds. */ public static List flatMap(final Collection c, final int fromIndex, final int toIndex, final Function> mapper) throws IndexOutOfBoundsException { return flatMap(c, fromIndex, toIndex, mapper, Factory.ofList()); } /** * Transforms the elements within the specified range in the input collection from type: {code T} to a collection of type: {@code R} by applying the specified {@code Function>} to each element. *
* The returned collection is created by the specified {@code supplier}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param The type of the elements in the input collection. * @param The type of the elements are mapped to. * @param The type of the returned collection * @param c The input collection to be transformed. * @param fromIndex the starting index (inclusive) of the range to be mapped * @param toIndex the ending index (exclusive) of the range to be mapped * @param mapper The function to transform each element in the input collection to a collection. * @param supplier The supplier used to create the returned collection. * @return A collection containing the transformed elements, or an empty collection created by the {@code supplier} if the input collection/range is {@code null} or empty. * @throws IndexOutOfBoundsException If the specified range is out of the collection's bounds. */ public static > C flatMap(final Collection c, final int fromIndex, final int toIndex, final Function> mapper, final IntFunction supplier) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); if ((isEmpty(c) && fromIndex == 0 && toIndex == 0) || fromIndex == toIndex) { return supplier.apply(0); } final int len = initSizeForFlatMap(toIndex - fromIndex); final C result = supplier.apply(len); Collection mr = null; if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; for (int i = fromIndex; i < toIndex; i++) { if (notEmpty(mr = mapper.apply(list.get(i)))) { result.addAll(mr); } } } else { int idx = 0; for (final T e : c) { if (idx++ < fromIndex) { continue; } if (notEmpty(mr = mapper.apply(e))) { result.addAll(mr); } if (idx >= toIndex) { break; } } } return result; } /** * Transforms the elements in the specified iterable from type: {code T} to a collection of type: {@code R} by applying the specified {@code Function>} to each element. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param The type of the elements in the iterable. * @param The type of the elements are mapped to. * @param c The input iterable to be transformed. * @param mapper The function to transform each element in the input iterable to a collection. * @return A list containing the transformed elements, or an empty list if the input iterable is {@code null} or empty. */ public static List flatMap(final Iterable c, final Function> mapper) { return flatMap(c, mapper, Factory.ofList()); } /** * Transforms the elements in the specified iterable from type: {code T} to a collection of type: {@code R} by applying the specified {@code Function>} to each element. *
* The returned collection is created by the specified {@code supplier}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param The type of the elements in the iterable. * @param The type of the elements are mapped to. * @param The type of the returned collection * @param c The input iterable to be transformed. * @param mapper The function to transform each element in the input iterable to a collection. * @param supplier The supplier used to create the returned collection. * @return A collection containing the transformed elements, or an empty collection created by the {@code supplier} if the input iterable is {@code null} or empty. */ public static > C flatMap(final Iterable c, final Function> mapper, final IntFunction supplier) throws IndexOutOfBoundsException { if (isEmptyCollection(c)) { return supplier.apply(0); } final C result = supplier.apply(initSizeForFlatMap(c)); Collection mr = null; for (final T e : c) { if (notEmpty(mr = mapper.apply(e))) { result.addAll(mr); } } return result; } /** * Transforms the elements in the specified iterator from type: {code T} to a collection of type: {@code R} by applying the specified {@code Function>} to each element. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param The type of the elements in the iterator. * @param The type of the elements are mapped to. * @param iter The input iterator to be transformed. * @param mapper The function to transform each element in the input iterator to a collection. * @return A list containing the transformed elements, or an empty list if the input iterator is {@code null} or empty. * @see Iterators#flatMap(Iterator, Function) */ public static List flatMap(final Iterator iter, final Function> mapper) { return flatMap(iter, mapper, Factory.ofList()); } /** * Transforms the elements in the specified iterator from type: {code T} to a collection of type: {@code R} by applying the specified {@code Function>} to each element. *
* The returned collection is created by the specified {@code supplier}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param The type of the elements in the iterator. * @param The type of the elements are mapped to. * @param The type of the returned collection * @param iter The input iterator to be transformed. * @param mapper The function to transform each element in the input iterator to a collection. * @param supplier The supplier used to create the returned collection. * @return A collection containing the transformed elements, or an empty collection created by the {@code supplier} if the input iterator is {@code null} or empty. * @see Iterators#flatMap(Iterator, Function) */ public static > C flatMap(final Iterator iter, final Function> mapper, final IntFunction supplier) throws IndexOutOfBoundsException { if (iter == null) { return supplier.apply(0); } final C result = supplier.apply(9); Collection mr = null; while (iter.hasNext()) { if (notEmpty(mr = mapper.apply(iter.next()))) { result.addAll(mr); } } return result; } /** * Transforms the elements in the specified array from type {@code T} to a collection of type {@code R} * by applying the specified {@code Function>} to each element, and then applying * the specified {@code Function>} to each element in the intermediate collections. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the input array * @param the intermediate type of the elements after the first mapping * @param the type of the elements in the resulting list * @param a the input array to be transformed * @param mapper the function to transform each element in the input array to a collection of type {@code U} * @param mapper2 the function to transform each element in the intermediate collections to a collection of type {@code R} * @return a list containing the transformed elements, or an empty list if the input array is {@code null} or empty */ public static List flatMap(final T[] a, final Function> mapper, final Function> mapper2) { return flatMap(a, mapper, mapper2, Factory.ofList()); } /** * Transforms the elements in the specified array from type {@code T} to a collection of type {@code R} * by applying the specified {@code Function>} to each element, and then applying * the specified {@code Function>} to each element in the intermediate collections. *
* The returned collection is created by the specified {@code supplier}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the input array * @param the intermediate type of the elements after the first mapping * @param the type of the elements in the resulting list * @param the type of the returned collection * @param a the input array to be transformed * @param mapper the function to transform each element in the input array to a collection of type {@code U} * @param mapper2 the function to transform each element in the intermediate collections to a collection of type {@code R} * @param supplier the supplier used to create the returned collection * @return a collection containing the transformed elements, or an empty collection created by the {@code supplier} if the input array is {@code null} or empty */ public static > C flatMap(final T[] a, final Function> mapper, final Function> mapper2, final IntFunction supplier) { if (isEmpty(a)) { return supplier.apply(0); } final int len = a.length > MAX_ARRAY_SIZE / LOAD_FACTOR_FOR_TWO_FLAT_MAP ? MAX_ARRAY_SIZE : a.length * LOAD_FACTOR_FOR_TWO_FLAT_MAP; final C result = supplier.apply(len); for (final T e : a) { final Collection c1 = mapper.apply(e); if (notEmpty(c1)) { for (final U e2 : c1) { final Collection c2 = mapper2.apply(e2); if (notEmpty(c2)) { result.addAll(c2); } } } } return result; } /** * Transforms the elements in the specified iterable from type {@code T} to a collection of type {@code R} * by applying the specified {@code Function>} to each element, and then applying * the specified {@code Function>} to each element in the intermediate collections. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the input iterable * @param the intermediate type of the elements after the first mapping * @param the type of the elements in the resulting list * @param c the input iterable to be transformed * @param mapper the function to transform each element in the input iterable to a collection of type {@code U} * @param mapper2 the function to transform each element in the intermediate collections to a collection of type {@code R} * @return a list containing the transformed elements, or an empty list if the input iterable is {@code null} or empty */ public static List flatMap(final Iterable c, final Function> mapper, final Function> mapper2) { return flatMap(c, mapper, mapper2, Factory.ofList()); } /** * Transforms the elements in the specified iterable from type {@code T} to a collection of type {@code R} * by applying the specified {@code Function>} to each element, and then applying * the specified {@code Function>} to each element in the intermediate collections. *
* The returned collection is created by the specified {@code supplier}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the input iterable * @param the intermediate type of the elements after the first mapping * @param the type of the elements in the resulting list * @param the type of the returned collection * @param c the input iterable to be transformed * @param mapper the function to transform each element in the input iterable to a collection of type {@code U} * @param mapper2 the function to transform each element in the intermediate collections to a collection of type {@code R} * @param supplier the supplier used to create the returned collection * @return a collection containing the transformed elements, or an empty collection created by the {@code supplier} if the input iterable is {@code null} or empty */ public static > C flatMap(final Iterable c, final Function> mapper, final Function> mapper2, final IntFunction supplier) { if (isEmptyCollection(c)) { return supplier.apply(0); } final C result = supplier.apply(initSizeForFlatMap(c)); for (final T e : c) { final Collection c1 = mapper.apply(e); if (notEmpty(c1)) { for (final U e2 : c1) { final Collection c2 = mapper2.apply(e2); if (notEmpty(c2)) { result.addAll(c2); } } } } return result; } /** * Transforms the elements in the specified iterator from type {@code T} to a collection of type {@code R} * by applying the specified {@code Function>} to each element, and then applying * the specified {@code Function>} to each element in the intermediate collections. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the input iterator * @param the intermediate type of the elements after the first mapping * @param the type of the elements in the resulting list * @param iter the input iterator to be transformed * @param mapper the function to transform each element in the input iterator to a collection of type {@code U} * @param mapper2 the function to transform each element in the intermediate collections to a collection of type {@code R} * @return a list containing the transformed elements, or an empty list if the input iterator is {@code null} or empty */ public static List flatMap(final Iterator iter, final Function> mapper, final Function> mapper2) { return flatMap(iter, mapper, mapper2, Factory.ofList()); } /** * Transforms the elements in the specified iterator from type {@code T} to a collection of type {@code R} * by applying the specified {@code Function>} to each element, and then applying * the specified {@code Function>} to each element in the intermediate collections. *
* The returned collection is created by the specified {@code supplier}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of the elements in the input iterator * @param the intermediate type of the elements after the first mapping * @param the type of the elements in the resulting list * @param the type of the returned collection * @param iter the input iterator to be transformed * @param mapper the function to transform each element in the input iterator to a collection of type {@code U} * @param mapper2 the function to transform each element in the intermediate collections to a collection of type {@code R} * @param supplier the supplier used to create the returned collection * @return a collection containing the transformed elements, or an empty collection created by the {@code supplier} if the input iterator is {@code null} or empty. */ public static > C flatMap(final Iterator iter, final Function> mapper, final Function> mapper2, final IntFunction supplier) { if (iter == null) { return supplier.apply(0); } final C result = supplier.apply(9); while (iter.hasNext()) { final Collection c1 = mapper.apply(iter.next()); if (notEmpty(c1)) { for (final U e2 : c1) { final Collection c2 = mapper2.apply(e2); if (notEmpty(c2)) { result.addAll(c2); } } } } return result; } // /** // * // * // * @param // * @param // * @param a // * @param mapper // * @return // */ // public static List flatmap(final T[] a, final Function mapper) { //NOSONAR // // if (isEmpty(a)) { // return new ArrayList<>(); // } // // return flatmap(a, 0, a.length, mapper); // } // // /** // * // * // * @param // * @param // * @param // * @param a // * @param mapper // * @param supplier // * @return // */ // public static > C flatmap(final T[] a, final Function mapper, //NOSONAR // final IntFunction supplier) { // if (isEmpty(a)) { // return supplier.apply(0); // } // // return flatmap(a, 0, a.length, mapper, supplier); // } // // /** // * Mostly it's designed for one-step operation to complete the operation in one step. // * {@code java.util.stream.Stream} is preferred for multiple phases operation. // * // * @param // * @param // * @param a // * @param fromIndex // * @param toIndex // * @param mapper // * @return // */ // public static List flatmap(final T[] a, final int fromIndex, final int toIndex, //NOSONAR // final Function mapper) { // return flatmap(a, fromIndex, toIndex, mapper, Factory.ofList()); // } // // /** // * Mostly it's designed for one-step operation to complete the operation in one step. // * {@code java.util.stream.Stream} is preferred for multiple phases operation. // * // * @param // * @param // * @param // * @param a // * @param fromIndex // * @param toIndex // * @param mapper // * @param supplier // * @return // * @throws IndexOutOfBoundsException // */ // public static > C flatmap(final T[] a, final int fromIndex, final int toIndex, //NOSONAR // final Function mapper, final IntFunction supplier) throws IndexOutOfBoundsException { // checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR // // if (isEmpty(a) || fromIndex == toIndex) { // return supplier.apply(0); // } // // final int len = initSizeForFlatMap(toIndex - fromIndex); // final C result = supplier.apply(len); // R[] mr = null; // // for (int i = fromIndex; i < toIndex; i++) { // if (notEmpty(mr = mapper.apply(a[i]))) { // result.addAll(Arrays.asList(mr)); // } // } // // return result; // } // // /** // * Mostly it's designed for one-step operation to complete the operation in one step. // * {@code java.util.stream.Stream} is preferred for multiple phases operation. // * // * @param // * @param // * @param c // * @param fromIndex // * @param toIndex // * @param mapper // * @return // */ // public static List flatmap(final Collection c, final int fromIndex, final int toIndex, //NOSONAR // final Function mapper) { // return flatmap(c, fromIndex, toIndex, mapper, Factory.ofList()); // } // // /** // * Mostly it's designed for one-step operation to complete the operation in one step. // * {@code java.util.stream.Stream} is preferred for multiple phases operation. // * // * @param // * @param // * @param // * @param c // * @param fromIndex // * @param toIndex // * @param mapper // * @param supplier // * @return // * @throws IndexOutOfBoundsException // */ // public static > C flatmap(final Collection c, final int fromIndex, final int toIndex, //NOSONAR // final Function mapper, final IntFunction supplier) throws IndexOutOfBoundsException { // checkFromToIndex(fromIndex, toIndex, size(c)); // // if ((isEmpty(c) && fromIndex == 0 && toIndex == 0) || fromIndex == toIndex) { // return supplier.apply(0); // } // // final int len = initSizeForFlatMap(toIndex - fromIndex); // final C result = supplier.apply(len); // R[] mr = null; // // if (c instanceof List && c instanceof RandomAccess) { // final List list = (List) c; // // for (int i = fromIndex; i < toIndex; i++) { // if (notEmpty(mr = mapper.apply(list.get(i)))) { // result.addAll(Arrays.asList(mr)); // } // } // } else { // int idx = 0; // // for (final T e : c) { // if (idx++ < fromIndex) { // continue; // } // // if (notEmpty(mr = mapper.apply(e))) { // result.addAll(Arrays.asList(mr)); // } // // if (idx >= toIndex) { // break; // } // } // } // // return result; // } // // /** // * // * // * @param // * @param // * @param c // * @param mapper // * @return // */ // public static List flatmap(final Iterable c, final Function mapper) //NOSONAR // { // return flatmap(c, mapper, Factory. ofList()); // } // // /** // * // * // * @param // * @param // * @param // * @param c // * @param mapper // * @param supplier // * @return // */ // public static > C flatmap(final Iterable c, //NOSONAR // final Function mapper, final IntFunction supplier) { // if (isEmptyCollection(c)) { // return supplier.apply(0); // } // // final C result = supplier.apply(initSizeForFlatMap(c)); // R[] mr = null; // // for (final T e : c) { // if (notEmpty(mr = mapper.apply(e))) { // result.addAll(Arrays.asList(mr)); // } // } // // return result; // } /** * Returns a list containing the elements of the input array until the provided predicate returns {@code false}. * * @param the type of elements in the input array * @param a the array to be processed * @param filter the predicate used to test elements * @return a list of elements from the input array starting from the first element until the predicate returns {@code false}. An empty list is returned if the input array is {@code null} or empty. */ public static List takeWhile(final T[] a, final Predicate filter) { if (isEmpty(a)) { return new ArrayList<>(0); } final List result = new ArrayList<>(min(9, len(a))); for (final T e : a) { if (filter.test(e)) { result.add(e); } else { break; } } return result; } /** * Returns a list containing the elements of the input iterable until the provided predicate returns {@code false}. * * @param the type of elements in the input iterable * @param c the iterable to be processed * @param filter the predicate used to test elements * @return a list of elements from the input iterable starting from the first element until the predicate returns {@code false}. An empty list is returned if the input iterable is {@code null} or empty. */ public static List takeWhile(final Iterable c, final Predicate filter) { if (isEmptyCollection(c)) { return new ArrayList<>(0); } final List result = new ArrayList<>(min(9, getSizeOrDefault(c, 0))); for (final T e : c) { if (filter.test(e)) { result.add(e); } else { break; } } return result; } /** * Returns a list containing the elements of the input iterator until the provided predicate returns {@code false}. * * @param the type of elements in the input iterator * @param iter the iterator to be processed * @param filter the predicate used to test elements * @return a list of elements from the input iterator starting from the first element until the predicate returns {@code false}. An empty list is returned if the input iterator is {@code null} or empty. */ public static List takeWhile(final Iterator iter, final Predicate filter) { if (iter == null) { return new ArrayList<>(0); } final List result = new ArrayList<>(9); T e = null; while (iter.hasNext()) { e = iter.next(); if (filter.test(e)) { result.add(e); } else { break; } } return result; } /** * Returns a list containing the elements of the input array until the provided predicate returns {@code false}, including the element that fails the predicate. * * @param the type of elements in the input array * @param a the array to process. * @param filter the predicate to apply to elements of the array. * @return a list of elements from the input array starting from the first element until the predicate returns {@code false}, including the element that fails the predicate. An empty list is returned if the input array is {@code null} or empty. */ public static List takeWhileInclusive(final T[] a, final Predicate filter) { if (isEmpty(a)) { return new ArrayList<>(0); } final List result = new ArrayList<>(min(9, len(a))); for (final T e : a) { result.add(e); if (!filter.test(e)) { break; } } return result; } /** * Returns a list containing the elements of the input iterable until the provided predicate returns {@code false}, including the element that fails the predicate. * * @param the type of elements in the input iterable * @param c the iterable to process. * @param filter the predicate to apply to elements of the iterable. * @return a list of elements from the input iterable starting from the first element until the predicate returns {@code false}, including the element that fails the predicate. An empty list is returned if the input iterable is {@code null} or empty. */ public static List takeWhileInclusive(final Iterable c, final Predicate filter) { if (isEmptyCollection(c)) { return new ArrayList<>(0); } final List result = new ArrayList<>(min(9, getSizeOrDefault(c, 0))); for (final T e : c) { result.add(e); if (!filter.test(e)) { break; } } return result; } /** * Returns a list containing the elements of the input iterator until the provided predicate returns {@code false}, including the element that fails the predicate. * * @param the type of elements in the input iterator * @param iter the iterator to process. * @param filter the predicate to apply to elements of the iterator. * @return a list of elements from the input iterator starting from the first element until the predicate returns {@code false}, including the element that fails the predicate. An empty list is returned if the input iterator is {@code null} or empty. */ public static List takeWhileInclusive(final Iterator iter, final Predicate filter) { if (iter == null) { return new ArrayList<>(0); } final List result = new ArrayList<>(9); T e = null; while (iter.hasNext()) { e = iter.next(); result.add(e); if (!filter.test(e)) { break; } } return result; } /** * Returns a list containing the elements of the input array after dropping the elements that satisfy the provided predicate. * * @param the type of elements in the input array * @param a the array to process. * @param filter the predicate to apply to elements of the array. * @return a list of elements from the input array starting from the first element that fails the predicate. An empty list is returned if the input array is {@code null} or empty. */ public static List dropWhile(final T[] a, final Predicate filter) { if (isEmpty(a)) { return new ArrayList<>(0); } final List result = new ArrayList<>(min(9, len(a))); final int len = a.length; int idx = 0; while (idx < len && filter.test(a[idx])) { idx++; } while (idx < len) { result.add(a[idx++]); } return result; } /** * Returns a list containing the elements of the input iterable after dropping the elements that satisfy the provided predicate. * * @param the type of elements in the input iterable * @param c the iterable to process. * @param filter the predicate to apply to elements of the iterable. * @return a list of elements from the input iterable starting from the first element that fails the predicate. An empty list is returned if the input iterable is {@code null} or empty. */ public static List dropWhile(final Iterable c, final Predicate filter) { if (isEmptyCollection(c)) { return new ArrayList<>(0); } return dropWhile(c.iterator(), filter, new ArrayList<>(min(9, getSizeOrDefault(c, 0)))); } /** * Returns a list containing the elements of the input iterator after dropping the elements that satisfy the provided predicate. * * @param the type of elements in the input iterator * @param iter the iterator to process. * @param filter the predicate to apply to elements of the iterator. * @return a list of elements from the input iterator starting from the first element that fails the predicate. An empty list is returned if the input iterator is {@code null} or empty. */ public static List dropWhile(final Iterator iter, final Predicate filter) { if (iter == null) { return new ArrayList<>(0); } return dropWhile(iter, filter, new ArrayList<>(9)); } private static List dropWhile(final Iterator iter, final Predicate filter, final List result) { T e = null; while (iter.hasNext()) { e = iter.next(); if (!filter.test(e)) { result.add(e); break; } } while (iter.hasNext()) { result.add(iter.next()); } return result; } /** * Returns a list containing the elements of the input array starting from the first element that satisfies the provided predicate. * * @param the type of elements in the input array * @param a the array to process. * @param filter the predicate to apply to elements of the array. * @return a list of elements from the input array starting from the first element that satisfies the predicate. An empty list if the input array is {@code null} or empty. */ public static List skipUntil(final T[] a, final Predicate filter) { if (isEmpty(a)) { return new ArrayList<>(0); } final List result = new ArrayList<>(min(9, len(a))); final int len = a.length; int idx = 0; while (idx < len && !filter.test(a[idx])) { idx++; } while (idx < len) { result.add(a[idx++]); } return result; } /** * Returns a list containing the elements of the input iterable starting from the first element that satisfies the provided predicate. * * @param the type of elements in the input iterable * @param c the iterable to process. * @param filter the predicate to apply to elements of the iterable. * @return a list of elements from the input iterable starting from the first element that satisfies the predicate. An empty list is returned if the input iterable is {@code null} or empty. */ public static List skipUntil(final Iterable c, final Predicate filter) { if (isEmptyCollection(c)) { return new ArrayList<>(0); } return skipUtil(c.iterator(), filter, new ArrayList<>(min(9, getSizeOrDefault(c, 0)))); } /** * Returns a list containing the elements of the input iterator starting from the first element that satisfies the provided predicate. * * @param the type of elements in the input iterable * @param iter the iterator to process. * @param filter the predicate to apply to elements of the iterator. * @return a list of elements from the input iterator starting from the first element that satisfies the predicate. An empty list is returned if the input iterator is {@code null} or empty. */ public static List skipUntil(final Iterator iter, final Predicate filter) { if (iter == null) { return new ArrayList<>(0); } return skipUtil(iter, filter, new ArrayList<>(9)); } private static List skipUtil(final Iterator iter, final Predicate filter, final List result) { T e = null; while (iter.hasNext()) { e = iter.next(); if (filter.test(e)) { result.add(e); break; } } while (iter.hasNext()) { result.add(iter.next()); } return result; } // /** // * // * // * @param // * @param // * @param a // * @param mapper // * @return // */ // public static List flatmap(final T[] a, final Function mapper) { //NOSONAR // // if (isEmpty(a)) { // return new ArrayList<>(); // } // // return flatmap(a, 0, a.length, mapper); // } // // /** // * // * // * @param // * @param // * @param // * @param a // * @param mapper // * @param supplier // * @return // */ // public static > C flatmap(final T[] a, final Function mapper, //NOSONAR // final IntFunction supplier) { // if (isEmpty(a)) { // return supplier.apply(0); // } // // return flatmap(a, 0, a.length, mapper, supplier); // } // // /** // * Mostly it's designed for one-step operation to complete the operation in one step. // * {@code java.util.stream.Stream} is preferred for multiple phases operation. // * // * @param // * @param // * @param a // * @param fromIndex // * @param toIndex // * @param mapper // * @return // */ // public static List flatmap(final T[] a, final int fromIndex, final int toIndex, //NOSONAR // final Function mapper) { // return flatmap(a, fromIndex, toIndex, mapper, Factory.ofList()); // } // // /** // * Mostly it's designed for one-step operation to complete the operation in one step. // * {@code java.util.stream.Stream} is preferred for multiple phases operation. // * // * @param // * @param // * @param // * @param a // * @param fromIndex // * @param toIndex // * @param mapper // * @param supplier // * @return // * @throws IndexOutOfBoundsException // */ // public static > C flatmap(final T[] a, final int fromIndex, final int toIndex, //NOSONAR // final Function mapper, final IntFunction supplier) throws IndexOutOfBoundsException { // checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR // // if (isEmpty(a) || fromIndex == toIndex) { // return supplier.apply(0); // } // // final int len = initSizeForFlatMap(toIndex - fromIndex); // final C result = supplier.apply(len); // R[] mr = null; // // for (int i = fromIndex; i < toIndex; i++) { // if (notEmpty(mr = mapper.apply(a[i]))) { // result.addAll(Arrays.asList(mr)); // } // } // // return result; // } // // /** // * Mostly it's designed for one-step operation to complete the operation in one step. // * {@code java.util.stream.Stream} is preferred for multiple phases operation. // * // * @param // * @param // * @param c // * @param fromIndex // * @param toIndex // * @param mapper // * @return // */ // public static List flatmap(final Collection c, final int fromIndex, final int toIndex, //NOSONAR // final Function mapper) { // return flatmap(c, fromIndex, toIndex, mapper, Factory.ofList()); // } // // /** // * Mostly it's designed for one-step operation to complete the operation in one step. // * {@code java.util.stream.Stream} is preferred for multiple phases operation. // * // * @param // * @param // * @param // * @param c // * @param fromIndex // * @param toIndex // * @param mapper // * @param supplier // * @return // * @throws IndexOutOfBoundsException // */ // public static > C flatmap(final Collection c, final int fromIndex, final int toIndex, //NOSONAR // final Function mapper, final IntFunction supplier) throws IndexOutOfBoundsException { // checkFromToIndex(fromIndex, toIndex, size(c)); // // if ((isEmpty(c) && fromIndex == 0 && toIndex == 0) || fromIndex == toIndex) { // return supplier.apply(0); // } // // final int len = initSizeForFlatMap(toIndex - fromIndex); // final C result = supplier.apply(len); // R[] mr = null; // // if (c instanceof List && c instanceof RandomAccess) { // final List list = (List) c; // // for (int i = fromIndex; i < toIndex; i++) { // if (notEmpty(mr = mapper.apply(list.get(i)))) { // result.addAll(Arrays.asList(mr)); // } // } // } else { // int idx = 0; // // for (final T e : c) { // if (idx++ < fromIndex) { // continue; // } // // if (notEmpty(mr = mapper.apply(e))) { // result.addAll(Arrays.asList(mr)); // } // // if (idx >= toIndex) { // break; // } // } // } // // return result; // } // // /** // * // * // * @param // * @param // * @param c // * @param mapper // * @return // */ // public static List flatmap(final Iterable c, final Function mapper) //NOSONAR // { // return flatmap(c, mapper, Factory. ofList()); // } // // /** // * // * // * @param // * @param // * @param // * @param c // * @param mapper // * @param supplier // * @return // */ // public static > C flatmap(final Iterable c, //NOSONAR // final Function mapper, final IntFunction supplier) { // if (isEmptyCollection(c)) { // return supplier.apply(0); // } // // final C result = supplier.apply(initSizeForFlatMap(c)); // R[] mr = null; // // for (final T e : c) { // if (notEmpty(mr = mapper.apply(e))) { // result.addAll(Arrays.asList(mr)); // } // } // // return result; // } /** * Maps and filters the elements in the given iterable. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of elements in the input iterable * @param the type of elements in the resulting list * @param c the input iterable * @param mapper the function to apply to each element * @param filter the predicate to apply to each mapped element * @return a list of elements that have been mapped and filtered. An empty list is returned if the input iterable is {@code null} or empty. * @see Factory#ofList() * @see Factory#ofSet() */ @Beta public static List mapAndFilter(final Iterable c, final Function mapper, final Predicate filter) { return mapAndFilter(c, mapper, filter, Factory.ofList()); } /** * Maps and filters the elements in the given iterable. *
* The returned collection is created by the specified {@code supplier}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of elements in the input iterable * @param the type of elements in the resulting collection * @param the type of the resulting collection * @param c the input iterable * @param mapper the function to apply to each element * @param filter the predicate to apply to each mapped element * @param supplier the supplier used to create the returned collection * @return a collection of elements that have been mapped and filtered. An empty collection created by the specified {@code supplier} is returned if the input iterable is {@code null} or empty. * @see Factory#ofList() * @see Factory#ofSet() */ @Beta public static > C mapAndFilter(final Iterable c, final Function mapper, final Predicate filter, final IntFunction supplier) { if (isEmptyCollection(c)) { return supplier.apply(0); } final C result = supplier.apply(getSizeOrDefault(c, 0) / 2); R val = null; for (final T e : c) { val = mapper.apply(e); if (filter.test(val)) { result.add(val); } } return result; } /** * Filters and maps the elements in the given iterable. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of elements in the input iterable * @param the type of elements in the resulting list * @param c the input iterable * @param filter the predicate to apply to each element * @param mapper the function to apply to each filtered element * @return a list of elements that have been filtered and mapped. An empty list is returned if the input iterable is {@code null} or empty. * @see Factory#ofList() * @see Factory#ofSet() */ @Beta public static List filterAndMap(final Iterable c, final Predicate filter, final Function mapper) { return filterAndMap(c, filter, mapper, Factory.ofList()); } /** * Filters and maps the elements in the given iterable. *
* The returned collection is created by the specified {@code supplier}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of elements in the input iterable * @param the type of elements in the resulting collection * @param the type of the resulting collection * @param c the input iterable * @param filter the predicate to apply to each element * @param mapper the function to apply to each filtered element * @param supplier the supplier used to create the returned collection * @return a collection of elements that have been filtered and mapped. An empty collection created by the specified {@code supplier} is returned if the input iterable is {@code null} or empty. * @see Factory#ofList() * @see Factory#ofSet() */ @Beta public static > C filterAndMap(final Iterable c, final Predicate filter, final Function mapper, final IntFunction supplier) { if (isEmptyCollection(c)) { return supplier.apply(0); } final C result = supplier.apply(getSizeOrDefault(c, 0) / 2); for (final T e : c) { if (filter.test(e)) { result.add(mapper.apply(e)); } } return result; } /** * Flat-maps and filters the elements in the given iterable. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of elements in the input iterable * @param the type of elements in the resulting collection * @param c the input iterable * @param mapper the function to apply to each element, which returns a collection of results * @param filter the predicate to apply to each element of the resulting collections * @return a list of elements that have been flat-mapped and filtered. An empty list is returned if the input iterable is {@code null} or empty. * @see Factory#ofList() * @see Factory#ofSet() */ @Beta public static List flatMapAndFilter(final Iterable c, final Function> mapper, final Predicate filter) { return flatMapAndFilter(c, mapper, filter, Factory.ofList()); } /** * Flat-maps and filters the elements in the given iterable. *
* The returned collection is created by the specified {@code supplier}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of elements in the input iterable * @param the type of elements in the resulting collection * @param the type of the resulting collection * @param c the input iterable * @param mapper the function to apply to each element, which returns a collection of results * @param filter the predicate to apply to each element of the resulting collections * @param supplier the supplier used to create the returned collection * @return a collection of elements that have been flat-mapped and filtered. An empty collection created by the specified {@code supplier} is returned if the input iterable is {@code null} or empty. * @see Factory#ofList() * @see Factory#ofSet() */ @Beta public static > C flatMapAndFilter(final Iterable c, final Function> mapper, final Predicate filter, final IntFunction supplier) { if (isEmptyCollection(c)) { return supplier.apply(0); } final C result = supplier.apply(getSizeOrDefault(c, 0) / 2); Collection vals = null; for (final T e : c) { vals = mapper.apply(e); if (notEmpty(vals)) { for (final R val : vals) { if (filter.test(val)) { result.add(val); } } } } return result; } /** * Filters and flat-maps the elements in the given iterable. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of elements in the input iterable * @param the type of elements in the resulting list * @param c the input iterable * @param filter the predicate to apply to each element to determine if it should be included * @param mapper the function to apply to each filtered element, which returns a collection of results * @return a list of elements that have been filtered and flat-mapped. An empty list is returned if the input iterable is {@code null} or empty. * @see Factory#ofList() * @see Factory#ofSet() */ @Beta public static List filterAndFlatMap(final Iterable c, final Predicate filter, final Function> mapper) { return filterAndFlatMap(c, filter, mapper, Factory.ofList()); } /** * Filters and flat-maps the elements in the given iterable. *
* The returned collection is created by the specified {@code supplier}. *

* Mostly it's designed for one-step operation. * {@code java.util.stream.Stream} is preferred for multiple phases operation. *

* * @param the type of elements in the input iterable * @param the type of elements in the resulting collection * @param the type of the resulting collection * @param c the input iterable * @param filter the predicate to apply to each element to determine if it should be included * @param mapper the function to apply to each filtered element, which returns a collection of results * @param supplier the supplier used to create the returned collection * @return a collection of elements that have been filtered and flat-mapped. An empty collection created by the specified {@code supplier} is returned if the input iterable is {@code null} or empty. * @see Factory#ofList() * @see Factory#ofSet() */ @Beta public static > C filterAndFlatMap(final Iterable c, final Predicate filter, final Function> mapper, final IntFunction supplier) { if (isEmptyCollection(c)) { return supplier.apply(0); } final C result = supplier.apply(getSizeOrDefault(c, 0) / 2); Collection vals = null; for (final T e : c) { if (filter.test(e)) { vals = mapper.apply(e); if (notEmpty(vals)) { result.addAll(vals); } } } return result; } private static int getSizeOrDefault(final Iterable c, final int defaultSize) { return c instanceof Collection ? ((Collection) c).size() : defaultSize; } private static int getMinSize(final Iterable c) { return min(9, getSizeOrDefault(c, 0)); } private static int initSizeForFlatMap(final Iterable c) { return c instanceof Collection ? initSizeForFlatMap(((Collection) c).size()) : 0; } private static int initSizeForFlatMap(final int size) { return size > MAX_ARRAY_SIZE / LOAD_FACTOR_FOR_FLAT_MAP ? MAX_ARRAY_SIZE : (int) (size * LOAD_FACTOR_FOR_FLAT_MAP); // NOSONAR } /** * Returns a new array containing only the distinct elements from the specified array. * * @param a the input array of boolean values * @return a new array containing only the distinct elements from the specified array. An empty array is returned if the specified array is {@code null} or empty. */ public static boolean[] distinct(final boolean[] a) { return distinct(a, 0, len(a)); // NOSONAR } /** * Returns a new array containing only the distinct elements from the specified range in the input array. * * @param a the input array of boolean values * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @return a new array containing only the distinct elements from the specified range in the input array. An empty array is returned if the specified array/range is {@code null} or empty. * @throws IndexOutOfBoundsException if the specified range is out of bounds */ public static boolean[] distinct(final boolean[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { return removeDuplicates(a, fromIndex, toIndex); } /** * Returns a new array containing only the distinct elements from the specified array. * * @param a the input array of char values * @return a new array containing only the distinct elements from the specified array. An empty array is returned if the specified array is {@code null} or empty. */ public static char[] distinct(final char[] a) { return distinct(a, 0, len(a)); // NOSONAR } /** * Returns a new array containing only the distinct elements from the specified range in the input array. * * @param a the input array of char values * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @return a new array containing only the distinct elements from the specified range in the input array. An empty array is returned if the specified array/range is {@code null} or empty. * @throws IndexOutOfBoundsException if the specified range is out of bounds */ public static char[] distinct(final char[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { return removeDuplicates(a, fromIndex, toIndex, false); } /** * Returns a new array containing only the distinct elements from the specified array. * * @param a the input array of byte values * @return a new array containing only the distinct elements from the specified array. An empty array is returned if the specified array is {@code null} or empty. */ public static byte[] distinct(final byte[] a) { return distinct(a, 0, len(a)); // NOSONAR } /** * Returns a new array containing only the distinct elements from the specified range in the input array. * * @param a the input array of byte values * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @return a new array containing only the distinct elements from the specified range in the input array. An empty array is returned if the specified array/range is {@code null} or empty. * @throws IndexOutOfBoundsException if the specified range is out of bounds */ public static byte[] distinct(final byte[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { return removeDuplicates(a, fromIndex, toIndex, false); } /** * Returns a new array containing only the distinct elements from the specified array. * * @param a the input array of short values * @return a new array containing only the distinct elements from the specified array. An empty array is returned if the specified array is {@code null} or empty. */ public static short[] distinct(final short[] a) { return distinct(a, 0, len(a)); // NOSONAR } /** * Returns a new array containing only the distinct elements from the specified range in the input array. * * @param a the input array of short values * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @return a new array containing only the distinct elements from the specified range in the input array. An empty array is returned if the specified array/range is {@code null} or empty. * @throws IndexOutOfBoundsException if the specified range is out of bounds */ public static short[] distinct(final short[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { return removeDuplicates(a, fromIndex, toIndex, false); } /** * Returns a new array containing only the distinct elements from the specified array. * * @param a the input array of int values * @return a new array containing only the distinct elements from the specified array. An empty array is returned if the specified array is {@code null} or empty. */ public static int[] distinct(final int[] a) { return distinct(a, 0, len(a)); // NOSONAR } /** * Returns a new array containing only the distinct elements from the specified range in the input array. * * @param a the input array of int values * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @return a new array containing only the distinct elements from the specified range in the input array. An empty array is returned if the specified array/range is {@code null} or empty. * @throws IndexOutOfBoundsException if the specified range is out of bounds */ public static int[] distinct(final int[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { return removeDuplicates(a, fromIndex, toIndex, false); } /** * Returns a new array containing only the distinct elements from the specified array. * * @param a the input array of long values * @return a new array containing only the distinct elements from the specified array. An empty array is returned if the specified array is {@code null} or empty. */ public static long[] distinct(final long[] a) { return distinct(a, 0, len(a)); // NOSONAR } /** * Returns a new array containing only the distinct elements from the specified range in the input array. * * @param a the input array of long values * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @return a new array containing only the distinct elements from the specified range in the input array. An empty array is returned if the specified array/range is {@code null} or empty. * @throws IndexOutOfBoundsException if the specified range is out of bounds */ public static long[] distinct(final long[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { return removeDuplicates(a, fromIndex, toIndex, false); } /** * Returns a new array containing only the distinct elements from the specified array. * * @param a the input array of float values * @return a new array containing only the distinct elements from the specified array. An empty array is returned if the specified array is {@code null} or empty. */ public static float[] distinct(final float[] a) { return distinct(a, 0, len(a)); // NOSONAR } /** * Returns a new array containing only the distinct elements from the specified range in the input array. * * @param a the input array of float values * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @return a new array containing only the distinct elements from the specified range in the input array. An empty array is returned if the specified array/range is {@code null} or empty. * @throws IndexOutOfBoundsException if the specified range is out of bounds */ public static float[] distinct(final float[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { return removeDuplicates(a, fromIndex, toIndex, false); } /** * Returns a new array containing only the distinct elements from the specified array. * * @param a the input array of double values * @return a new array containing only the distinct elements from the specified array. An empty array is returned if the specified array is {@code null} or empty. */ public static double[] distinct(final double[] a) { return distinct(a, 0, len(a)); // NOSONAR } /** * Returns a new array containing only the distinct elements from the specified range in the input array. * * @param a the input array of double values * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @return a new array containing only the distinct elements from the specified range in the input array. An empty array is returned if the specified array/range is {@code null} or empty. * @throws IndexOutOfBoundsException if the specified range is out of bounds */ public static double[] distinct(final double[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { return removeDuplicates(a, fromIndex, toIndex, false); } /** * Returns a new list containing only the distinct elements from the specified array. * * @param the type of elements in the input array * @param a the input array * @return a new list containing only the distinct elements from the specified array. An empty list is returned if the input array is {@code null} or empty. * @see #removeDuplicates(Object[]) */ public static List distinct(final T[] a) { if (isEmpty(a)) { return new ArrayList<>(); } return distinct(a, 0, a.length); } /** * Returns a new list containing only the distinct elements from the specified range in the input array. * * @param the type of elements in the input array * @param a the input array * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @return a new list containing only the distinct elements from the specified range in the input array. An empty list is returned if the input array/range is {@code null} or empty. * @throws IndexOutOfBoundsException if the specified range is out of bounds * @see #removeDuplicates(Object[], int, int, boolean) */ public static List distinct(final T[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return new ArrayList<>(); } final int initCapacity = (toIndex - fromIndex) / 2 + 1; final List result = new ArrayList<>(initCapacity); final Set set = newHashSet(initCapacity); for (int i = fromIndex; i < toIndex; i++) { if (set.add(hashKey(a[i]))) { result.add(a[i]); } } return result; } /** * Returns a new list containing only the distinct elements from the specified range in the input collection. * * @param the type of elements in the input collection * @param c the input collection * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @return a new list containing only the distinct elements from the specified range in the input collection. An empty list is returned if the input collection/range is {@code null} or empty. * @throws IndexOutOfBoundsException if the specified range is out of bounds * @see #removeDuplicates(Collection, boolean) */ public static List distinct(final Collection c, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); if ((isEmpty(c) && fromIndex == 0 && toIndex == 0) || fromIndex == toIndex) { return new ArrayList<>(); } final int initCapacity = (toIndex - fromIndex) / 2 + 1; final List result = new ArrayList<>(initCapacity); final Set set = newHashSet(initCapacity); T e = null; if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; for (int i = fromIndex; i < toIndex; i++) { e = list.get(i); if (set.add(hashKey(e))) { result.add(e); } } } else { final Iterator it = c.iterator(); for (int i = 0; i < toIndex && it.hasNext(); i++) { e = it.next(); if (i < fromIndex) { continue; } if (set.add(hashKey(e))) { result.add(e); } } } return result; } /** * Returns a new list containing only the distinct elements from the specified iterable. * * @param the type of elements in the input iterable * @param c the input iterable * @return a new list containing only the distinct elements from the specified iterable. An empty list is returned if the input iterable is {@code null} or empty * @see #removeDuplicates(Collection) */ public static List distinct(final Iterable c) { if (isEmptyCollection(c)) { return new ArrayList<>(); } else if (c instanceof Collection) { final Collection coll = (Collection) c; return distinct(coll, 0, coll.size()); } else { final List result = new ArrayList<>(); final Set set = new HashSet<>(); for (final T e : c) { if (set.add(hashKey(e))) { result.add(e); } } return result; } } /** * Returns a new list containing only the distinct elements from the specified iterator. * * @param the type of elements in the input iterator * @param iter the input iterator * @return a new list containing only the distinct elements from the specified iterator. An empty list is returned if the input iterator is {@code null} or empty * @see Iterators#distinct(Iterator) * @see Iterators#distinct(Iterable) * @see Iterators#distinctBy(Iterator, Function) * @see Iterators#distinctBy(Iterable, Function) */ public static List distinct(final Iterator iter) { return distinctBy(iter, Fn.identity()); } /** * Returns a new list containing only the distinct elements from the specified array, where distinctness is determined by the keys extracted by the specified {@code Function}. * * @param the type of elements in the input array * @param a the input array * @param keyExtractor the function to extract the key for distinct comparison * @return a new list containing only the distinct elements from the input array. An empty list is returned if the input array is {@code null} or empty */ public static List distinctBy(final T[] a, final Function keyExtractor) { if (isEmpty(a)) { return new ArrayList<>(); } return distinctBy(a, 0, a.length, keyExtractor); } /** * Returns a new list containing only the distinct elements from the specified range in the input array, where distinctness is determined by the keys extracted by the specified {@code Function}. * * @param the type of elements in the input array * @param a the input array * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @param keyExtractor the function to extract the key for distinct comparison * @return a new list containing only the distinct elements from the specified range in the input array. An empty list is returned if the input array/range is {@code null} or empty * @throws IndexOutOfBoundsException if the specified range is out of bounds */ public static List distinctBy(final T[] a, final int fromIndex, final int toIndex, final Function keyExtractor) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return new ArrayList<>(); } final int initCapacity = (toIndex - fromIndex) / 2 + 1; final List result = new ArrayList<>(initCapacity); final Set set = newHashSet(initCapacity); for (int i = fromIndex; i < toIndex; i++) { if (set.add(hashKey(keyExtractor.apply(a[i])))) { result.add(a[i]); } } return result; } /** * Returns a new collection containing only the distinct elements from the specified array, where distinctness is determined by the keys extracted by the specified {@code Function}. * The returned collection is created by the specified {@code supplier}. * * @param the type of elements in the input array * @param a the input array * @param keyExtractor the function to extract the key for distinct comparison * @param supplier the supplier used to create the returned collection * @return a new collection containing only the distinct elements from the input array. An empty collection is returned if the input array is {@code null} or empty */ public static > C distinctBy(final T[] a, final Function keyExtractor, final Supplier supplier) { if (isEmpty(a)) { return supplier.get(); } final C result = supplier.get(); final Set set = newHashSet(len(a) / 2 + 1); for (final T e : a) { if (set.add(hashKey(keyExtractor.apply(e)))) { result.add(e); } } return result; } /** * Returns a new list containing only the distinct elements from the specified range in the input collection, where distinctness is determined by the keys extracted by the specified {@code Function}. * * @param the type of elements in the input collection * @param c the input collection * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @param keyExtractor the function to extract the key for distinct comparison * @return a new list containing only the distinct elements from the specified range in the input collection. An empty list is returned if the input collection/range is {@code null} or empty * @throws IndexOutOfBoundsException if the specified range is out of bounds */ public static List distinctBy(final Collection c, final int fromIndex, final int toIndex, final Function keyExtractor) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); if ((isEmpty(c) && fromIndex == 0 && toIndex == 0) || fromIndex == toIndex) { return new ArrayList<>(); } final int initCapacity = (toIndex - fromIndex) / 2 + 1; final List result = new ArrayList<>(initCapacity); final Set set = newHashSet(initCapacity); T e = null; if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; for (int i = fromIndex; i < toIndex; i++) { e = list.get(i); if (set.add(hashKey(keyExtractor.apply(e)))) { result.add(e); } } } else { final Iterator it = c.iterator(); for (int i = 0; i < toIndex && it.hasNext(); i++) { e = it.next(); if (i < fromIndex) { continue; } if (set.add(hashKey(keyExtractor.apply(e)))) { result.add(e); } } } return result; } /** * Returns a new list containing only the distinct elements from the specified iterable, where distinctness is determined by the keys extracted by the specified {@code Function}. * * @param the type of elements in the input iterable * @param c the input iterable * @param keyExtractor the function to extract the key for distinct comparison * @return a new list containing only the distinct elements from the specified iterable. An empty list is returned if the input iterable is {@code null} or empty */ public static List distinctBy(final Iterable c, final Function keyExtractor) { return distinctBy(c, keyExtractor, Suppliers.ofList()); } /** * Returns a new collection containing only the distinct elements from the specified iterable, where distinctness is determined by the keys extracted by the specified {@code Function}. * The returned collection is created by the specified {@code supplier}. * * @param the type of elements in the input iterable * @param the type of the resulting collection * @param c the input iterable * @param keyExtractor the function to extract the key for distinct comparison * @param supplier the supplier used to create the returned collection * @return a new collection containing only the distinct elements from the input iterable. An empty collection is returned if the input iterable is {@code null} or empty */ public static > C distinctBy(final Iterable c, final Function keyExtractor, final Supplier supplier) { if (isEmptyCollection(c)) { return supplier.get(); } final C result = supplier.get(); final Set set = newHashSet(c instanceof Collection ? ((Collection) c).size() / 2 + 1 : 0); for (final T e : c) { if (set.add(hashKey(keyExtractor.apply(e)))) { result.add(e); } } return result; } /** * Returns a new list containing only the distinct elements from the specified iterator, where distinctness is determined by the keys extracted by the specified {@code Function}. * * @param the type of elements in the input iterator * @param iter the input iterator * @param keyExtractor the function to extract the key for distinct comparison * @return a new list containing only the distinct elements from the specified iterator. An empty list is returned if the input iterator is {@code null} or empty * @see Iterators#distinct(Iterator) * @see Iterators#distinct(Iterable) * @see Iterators#distinctBy(Iterator, Function) * @see Iterators#distinctBy(Iterable, Function) */ public static List distinctBy(final Iterator iter, final Function keyExtractor) { return distinctBy(iter, keyExtractor, Suppliers.ofList()); } /** * Returns a new collection containing only the distinct elements from the specified iterator, where distinctness is determined by the keys extracted by the specified {@code Function}. * The returned collection is created by the specified {@code supplier}. * * @param the type of elements in the input iterator * @param the type of the resulting collection * @param iter the input iterator * @param keyExtractor the function to extract the key for distinct comparison * @param supplier the supplier used to create the returned collection * @return a new collection containing only the distinct elements from the input iterator. An empty collection is returned if the input iterator is {@code null} or empty */ public static > C distinctBy(final Iterator iter, final Function keyExtractor, final Supplier supplier) { if (iter == null) { return supplier.get(); } final C result = supplier.get(); final Set set = new HashSet<>(); T next = null; while (iter.hasNext()) { next = iter.next(); if (set.add(hashKey(keyExtractor.apply(next)))) { result.add(next); } } return result; } /** * Checks if all elements in the input array match the given predicate. * * @param the type of elements in the input array * @param a the input array * @param filter the predicate to apply to each element * @return {@code true} if all elements match the predicate or the input array is {@code null} or empty, {@code false} otherwise */ public static boolean allMatch(final T[] a, final Predicate filter) { if (isEmpty(a)) { return true; } for (final T e : a) { if (!filter.test(e)) { return false; } } return true; } /** * Checks if all elements in the input iterable match the given predicate. * * @param the type of elements in the input iterable * @param c the input iterable * @param filter the predicate to apply to each element * @return {@code true} if all elements match the predicate or the input iterable is {@code null} or empty, {@code false} otherwise */ public static boolean allMatch(final Iterable c, final Predicate filter) { if (isEmptyCollection(c)) { return true; } for (final T e : c) { if (!filter.test(e)) { return false; } } return true; } /** * Checks if all elements in the input iterator match the given predicate. * * @param the type of elements in the input iterator * @param iter the input iterator * @param filter the predicate to apply to each element * @return {@code true} if all elements match the predicate or the input iterator is {@code null} or empty, {@code false} otherwise */ public static boolean allMatch(final Iterator iter, final Predicate filter) { if (iter == null) { return true; } while (iter.hasNext()) { if (!filter.test(iter.next())) { return false; } } return true; } /** * Checks if any element in the input array matches the given predicate. * * @param the type of elements in the input array * @param a the input array * @param filter the predicate to apply to each element * @return {@code true} if any element matches the predicate, {@code false} otherwise */ public static boolean anyMatch(final T[] a, final Predicate filter) { if (isEmpty(a)) { return false; } for (final T e : a) { if (filter.test(e)) { return true; } } return false; } /** * Checks if any element in the input iterable matches the given predicate. * * @param the type of elements in the input iterable * @param c the input iterable * @param filter the predicate to apply to each element * @return {@code true} if any element matches the predicate, {@code false} otherwise */ public static boolean anyMatch(final Iterable c, final Predicate filter) { if (isEmptyCollection(c)) { return false; } for (final T e : c) { if (filter.test(e)) { return true; } } return false; } /** * Checks if any element in the input iterator matches the given predicate. * * @param the type of elements in the input iterator * @param iter the input iterator * @param filter the predicate to apply to each element * @return {@code true} if any element matches the predicate, {@code false} otherwise */ public static boolean anyMatch(final Iterator iter, final Predicate filter) { if (iter == null) { return false; } while (iter.hasNext()) { if (filter.test(iter.next())) { return true; } } return false; } /** * Checks if none of the elements in the input array match the given predicate. * * @param the type of elements in the input array * @param a the input array * @param filter the predicate to apply to each element * @return {@code true} if none of the elements match the predicate or the input array is {@code null} or empty, {@code false} otherwise */ public static boolean noneMatch(final T[] a, final Predicate filter) { if (isEmpty(a)) { return true; } for (final T e : a) { if (filter.test(e)) { return false; } } return true; } /** * Checks if none of the elements in the input iterable match the given predicate. * * @param the type of elements in the input iterable * @param c the input iterable * @param filter the predicate to apply to each element * @return {@code true} if none of the elements match the predicate or the input iterable is {@code null} or empty, {@code false} otherwise */ public static boolean noneMatch(final Iterable c, final Predicate filter) { if (isEmptyCollection(c)) { return true; } for (final T e : c) { if (filter.test(e)) { return false; } } return true; } /** * Checks if none of the elements in the input iterator match the given predicate. * * @param the type of elements in the input iterator * @param iter the input iterator * @param filter the predicate to apply to each element * @return {@code true} if none of the elements match the predicate or the input iterator is {@code null} or empty, {@code false} otherwise */ public static boolean noneMatch(final Iterator iter, final Predicate filter) { if (iter == null) { return true; } while (iter.hasNext()) { if (filter.test(iter.next())) { return false; } } return true; } /** * Checks if the number of elements in the input array that match the given predicate is between the specified minimum and maximum values (inclusive). * * @param the type of elements in the input array * @param a the input array * @param {@code atLeast} the minimum number of elements that should match the predicate * @param {@code atMost} the maximum number of elements that should match the predicate * @param filter the predicate to apply to each element * @return {@code true} if the number of matching elements is between {@code atLeast} and {@code atMost} (inclusive), {@code false} otherwise * @throws IllegalArgumentException if {@code atLeast} or {@code atMost} is negative, or if {@code atLeast} is greater than atMost */ public static boolean nMatch(final T[] a, final int atLeast, final int atMost, final Predicate filter) { checkArgNotNegative(atLeast, "atLeast"); //NOSONAR checkArgNotNegative(atMost, "atMost"); //NOSONAR checkArgument(atLeast <= atMost, "'atLeast' must be <= 'atMost'"); //NOSONAR if (isEmpty(a)) { return atLeast == 0; } final int len = len(a); if (len < atLeast) { return false; } long cnt = 0; for (int i = 0; i < len; i++) { if (filter.test(a[i]) && (++cnt > atMost)) { return false; } } return cnt >= atLeast && cnt <= atMost; } /** * Checks if the number of elements in the input iterable that match the given predicate is between the specified minimum and maximum values (inclusive). * * @param the type of elements in the input iterable * @param c the input iterable * @param {@code atLeast} the minimum number of elements that should match the predicate * @param {@code atMost} the maximum number of elements that should match the predicate * @param filter the predicate to apply to each element * @return {@code true} if the number of matching elements is between {@code atLeast} and {@code atMost} (inclusive), {@code false} otherwise * @throws IllegalArgumentException if {@code atLeast} or {@code atMost} is negative, or if {@code atLeast} is greater than atMost */ public static boolean nMatch(final Iterable c, final int atLeast, final int atMost, final Predicate filter) { checkArgNotNegative(atLeast, cs.atLeast); checkArgNotNegative(atMost, cs.atMost); checkArgument(atLeast <= atMost, "'atLeast' must be <= 'atMost'"); if (isEmptyCollection(c)) { return atLeast == 0; } if (c instanceof final Collection coll) { // NOSONAR final int size = coll.size(); if (size < atLeast) { return false; } } return nMatch(c.iterator(), atLeast, atMost, filter); } /** * Checks if the number of elements in the input iterator that match the given predicate is between the specified minimum and maximum values (inclusive). * * @param the type of elements in the input iterator * @param iter the input iterator * @param {@code atLeast} the minimum number of elements that should match the predicate * @param {@code atMost} the maximum number of elements that should match the predicate * @param filter the predicate to apply to each element * @return {@code true} if the number of matching elements is between {@code atLeast} and {@code atMost} (inclusive), {@code false} otherwise * @throws IllegalArgumentException if {@code atLeast} or {@code atMost} is negative, or if {@code atLeast} is greater than atMost */ public static boolean nMatch(final Iterator iter, final int atLeast, final int atMost, final Predicate filter) { checkArgNotNegative(atLeast, cs.atLeast); checkArgNotNegative(atMost, cs.atMost); checkArgument(atLeast <= atMost, "'atLeast' must be <= 'atMost'"); if (iter == null) { return atLeast == 0; } long cnt = 0; while (iter.hasNext()) { if (filter.test(iter.next()) && (++cnt > atMost)) { return false; } } return cnt >= atLeast && cnt <= atMost; } /** * Checks if all elements in the input boolean array are {@code true}. * * @param a the input boolean array * @return {@code true} if all elements are {@code true} or the input array is {@code null} or empty, {@code false} otherwise */ public static boolean allTrue(final boolean[] a) { if (isEmpty(a)) { return true; } for (final boolean b : a) { if (!b) { return false; } } return true; } /** * Checks if all elements in the input boolean array are {@code false}. * * @param a the input boolean array * @return {@code true} if all elements are {@code false} or the input array is {@code null} or empty, {@code false} otherwise */ public static boolean allFalse(final boolean[] a) { if (isEmpty(a)) { return true; } for (final boolean b : a) { if (b) { return false; } } return true; } /** * Checks if any element in the input boolean array is {@code true}. * * @param a the input boolean array * @return {@code true} if any element is {@code true}, {@code false} otherwise */ public static boolean anyTrue(final boolean[] a) { if (isEmpty(a)) { return false; } for (final boolean b : a) { if (b) { return true; } } return false; } /** * Checks if any element in the input boolean array is {@code false}. * * @param a the input boolean array * @return {@code true} if any element is {@code false}, {@code false} otherwise */ public static boolean anyFalse(final boolean[] a) { if (isEmpty(a)) { return false; } for (final boolean b : a) { if (!b) { return true; } } return false; } /** * Counts the number of elements in the input boolean array that match the given predicate. * * @param a the input boolean array * @param filter the predicate to test if an element should be counted or not. * @return the number of elements that match the predicate. 0 is returned if the input array is {@code null} or empty */ public static int count(final boolean[] a, final BooleanPredicate filter) { if (isEmpty(a)) { return 0; } return count(a, 0, a.length, filter); } /** * Counts the number of elements within the specified range in the input boolean array that match the given predicate. * * @param a the input boolean array * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @param filter the predicate to test if an element should be counted or not. * @return the number of elements within the specified range in the input boolean array that match the given predicate. 0 is returned if the input array/range is {@code null} or empty * @throws IndexOutOfBoundsException if the specified range is out of bounds */ public static int count(final boolean[] a, final int fromIndex, final int toIndex, final BooleanPredicate filter) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0; } int count = 0; for (int i = fromIndex; i < toIndex; i++) { if (filter.test(a[i])) { count++; } } return count; } /** * Counts the number of elements in the input byte array that match the given predicate. * * @param a the input byte array * @param filter the predicate to test if an element should be counted or not. * @return the number of elements that match the predicate. 0 is returned if the input array is {@code null} or empty */ public static int count(final char[] a, final CharPredicate filter) { if (isEmpty(a)) { return 0; } return count(a, 0, a.length, filter); } /** * Counts the number of elements within the specified range in the input byte array that match the given predicate. * * @param a the input byte array * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @param filter the predicate to test if an element should be counted or not. * @return the number of elements within the specified range in the input byte array that match the given predicate. 0 is returned if the input array/range is {@code null} or empty * @throws IndexOutOfBoundsException if the specified range is out of bounds */ public static int count(final char[] a, final int fromIndex, final int toIndex, final CharPredicate filter) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0; } int count = 0; for (int i = fromIndex; i < toIndex; i++) { if (filter.test(a[i])) { count++; } } return count; } /** * Counts the number of elements in the input byte array that match the given predicate. * * @param a the input byte array * @param filter the predicate to test if an element should be counted or not. * @return the number of elements that match the predicate. 0 is returned if the input array is {@code null} or empty */ public static int count(final byte[] a, final BytePredicate filter) { if (isEmpty(a)) { return 0; } return count(a, 0, a.length, filter); } /** * Counts the number of elements within the specified range in the input byte array that match the given predicate. * * @param a the input byte array * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @param filter the predicate to test if an element should be counted or not. * @return the number of elements within the specified range in the input byte array that match the given predicate. 0 is returned if the input array/range is {@code null} or empty * @throws IndexOutOfBoundsException if the specified range is out of bounds */ public static int count(final byte[] a, final int fromIndex, final int toIndex, final BytePredicate filter) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0; } int count = 0; for (int i = fromIndex; i < toIndex; i++) { if (filter.test(a[i])) { count++; } } return count; } /** * Counts the number of elements in the input short array that match the given predicate. * * @param a the input short array * @param filter the predicate to test if an element should be counted or not. * @return the number of elements that match the predicate. 0 is returned if the input array is {@code null} or empty */ public static int count(final short[] a, final ShortPredicate filter) { if (isEmpty(a)) { return 0; } return count(a, 0, a.length, filter); } /** * Counts the number of elements within the specified range in the input short array that match the given predicate. * * @param a the input short array * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @param filter the predicate to test if an element should be counted or not. * @return the number of elements within the specified range in the input short array that match the given predicate. 0 is returned if the input array/range is {@code null} or empty * @throws IndexOutOfBoundsException if the specified range is out of bounds */ public static int count(final short[] a, final int fromIndex, final int toIndex, final ShortPredicate filter) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0; } int count = 0; for (int i = fromIndex; i < toIndex; i++) { if (filter.test(a[i])) { count++; } } return count; } /** * Counts the number of elements in the input int array that match the given predicate. * * @param a the input int array * @param filter the predicate to test if an element should be counted or not. * @return the number of elements that match the predicate. 0 is returned if the input array is {@code null} or empty */ public static int count(final int[] a, final IntPredicate filter) { if (isEmpty(a)) { return 0; } return count(a, 0, a.length, filter); } /** * Counts the number of elements within the specified range in the input int array that match the given predicate. * * @param a the input int array * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @param filter the predicate to test if an element should be counted or not. * @return the number of elements within the specified range in the input int array that match the given predicate. 0 is returned if the input array/range is {@code null} or empty * @throws IndexOutOfBoundsException if the specified range is out of bounds */ public static int count(final int[] a, final int fromIndex, final int toIndex, final IntPredicate filter) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0; } int count = 0; for (int i = fromIndex; i < toIndex; i++) { if (filter.test(a[i])) { count++; } } return count; } /** * Counts the number of elements in the input long array that match the given predicate. * * @param a the input long array * @param filter the predicate to test if an element should be counted or not. * @return the number of elements that match the predicate. 0 is returned if the input array is {@code null} or empty */ public static int count(final long[] a, final LongPredicate filter) { if (isEmpty(a)) { return 0; } return count(a, 0, a.length, filter); } /** * Counts the number of elements within the specified range in the input long array that match the given predicate. * * @param a the input long array * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @param filter the predicate to test if an element should be counted or not. * @return the number of elements within the specified range in the input long array that match the given predicate. 0 is returned if the input array/range is {@code null} or empty * @throws IndexOutOfBoundsException if the specified range is out of bounds */ public static int count(final long[] a, final int fromIndex, final int toIndex, final LongPredicate filter) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0; } int count = 0; for (int i = fromIndex; i < toIndex; i++) { if (filter.test(a[i])) { count++; } } return count; } /** * Counts the number of elements in the input float array that match the given predicate. * * @param a the input float array * @param filter the predicate to test if an element should be counted or not. * @return the number of elements that match the predicate. 0 is returned if the input array is {@code null} or empty */ public static int count(final float[] a, final FloatPredicate filter) { if (isEmpty(a)) { return 0; } return count(a, 0, a.length, filter); } /** * Counts the number of elements within the specified range in the input float array that match the given predicate. * * @param a the input float array * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @param filter the predicate to test if an element should be counted or not. * @return the number of elements within the specified range in the input float array that match the given predicate. 0 is returned if the input array/range is {@code null} or empty * @throws IndexOutOfBoundsException if the specified range is out of bounds */ public static int count(final float[] a, final int fromIndex, final int toIndex, final FloatPredicate filter) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0; } int count = 0; for (int i = fromIndex; i < toIndex; i++) { if (filter.test(a[i])) { count++; } } return count; } /** * Counts the number of elements in the input double array that match the given predicate. * * @param a the input double array * @param filter the predicate to test if an element should be counted or not. * @return the number of elements that match the predicate. 0 is returned if the input array is {@code null} or empty */ public static int count(final double[] a, final DoublePredicate filter) throws IndexOutOfBoundsException { if (isEmpty(a)) { return 0; } return count(a, 0, a.length, filter); } /** * Counts the number of elements within the specified range in the input double array that match the given predicate. * * @param a the input double array * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @param filter the predicate to test if an element should be counted or not. * @return the number of elements within the specified range in the input double array that match the given predicate. 0 is returned if the input array/range is {@code null} or empty * @throws IndexOutOfBoundsException if the specified range is out of bounds */ public static int count(final double[] a, final int fromIndex, final int toIndex, final DoublePredicate filter) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0; } int count = 0; for (int i = fromIndex; i < toIndex; i++) { if (filter.test(a[i])) { count++; } } return count; } /** * Counts the number of elements in the input array that match the given predicate. * * @param the type of elements in the input array * @param a the input array * @param filter the predicate to test if an element should be counted or not. * @return the number of elements that match the predicate. 0 is returned if the input array is {@code null} or empty */ public static int count(final T[] a, final Predicate filter) throws IndexOutOfBoundsException { if (isEmpty(a)) { return 0; } return count(a, 0, a.length, filter); } /** * Counts the number of elements within the specified range in the input array that match the given predicate. * * @param the type of elements in the input array * @param a the input array * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @param filter the predicate to test if an element should be counted or not. * @return the number of elements within the specified range in the input array that match the given predicate. 0 is returned if the input array/range is {@code null} or empty * @throws IndexOutOfBoundsException if the specified range is out of bounds */ public static int count(final T[] a, final int fromIndex, final int toIndex, final Predicate filter) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return 0; } int count = 0; for (int i = fromIndex; i < toIndex; i++) { if (filter.test(a[i])) { count++; } } return count; } /** * Counts the number of elements within the specified range in the input collection that match the given predicate. * * @param the type of elements in the input collection * @param c the input collection * @param fromIndex the starting index (inclusive) of the range * @param toIndex the ending index (exclusive) of the range * @param filter the predicate to test if an element should be counted or not. * @return the number of elements within the specified range in the input collection that match the given predicate. 0 is returned if the input collection/range is {@code null} or empty * @throws IndexOutOfBoundsException if the specified range is out of bounds */ public static int count(final Collection c, final int fromIndex, final int toIndex, final Predicate filter) throws IndexOutOfBoundsException { checkFromToIndex(fromIndex, toIndex, size(c)); if ((isEmpty(c) && fromIndex == 0 && toIndex == 0) || (fromIndex == toIndex && fromIndex < c.size())) { return 0; } int count = 0; if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; for (int i = fromIndex; i < toIndex; i++) { if (filter.test(list.get(i))) { count++; } } } else { int idx = 0; for (final T e : c) { if (idx++ < fromIndex) { continue; } if (filter.test(e)) { count++; } if (idx >= toIndex) { break; } } } return count; } /** * Counts the number of elements in the input iterable that match the given predicate. * * @param the type of elements in the input iterable * @param c the input iterable * @param filter the predicate to test if an element should be counted or not. * @return the number of elements that match the predicate. 0 is returned if the input iterable is {@code null} or empty */ public static int count(final Iterable c, final Predicate filter) { if (isEmptyCollection(c)) { return 0; } int count = 0; for (final T e : c) { if (filter.test(e)) { count++; } } return count; } /** * Counts the number of elements in the input iterator. * * @param iter the input iterator * @return the number of elements in the input iterator. 0 is returned if the input iterator is {@code null} or empty * @throws ArithmeticException if the total count overflows an {@code int} * @see Iterators#count(Iterator) * @see Iterators#count(Iterator, Predicate) */ public static int count(final Iterator iter) throws ArithmeticException { if (iter == null) { return 0; } return Numbers.toIntExact(Iterators.count(iter)); } /** * Counts the number of elements in the input iterator that match the given predicate. * * @param the type of elements in the input iterator * @param iter the input iterator * @param filter the predicate to test if an element should be counted or not. * @return the number of elements that match the predicate. 0 is returned if the input iterator is {@code null} or empty * @throws ArithmeticException if the total count overflows an {@code int} * @see Iterators#count(Iterator) * @see Iterators#count(Iterator, Predicate) */ public static int count(final Iterator iter, final Predicate filter) throws ArithmeticException { if (iter == null) { return 0; } return Numbers.toIntExact(Iterators.count(iter, filter)); } /** * Merges two the input arrays into a list based where the order of the elements is determined by the given selector function. * * @param the type of elements in the arrays * @param a the first array to merge * @param b the second array to merge * @param nextSelector a function that determines the next element to add to the result list * @return a list containing the merged elements from both arrays. An empty list is returned if both arrays are {@code null} or empty. * @see #concat(Object[], Object[]) */ public static List merge(final T[] a, final T[] b, final BiFunction nextSelector) { if (isEmpty(a)) { return isEmpty(b) ? new ArrayList<>() : asList(b); } else if (isEmpty(b)) { return asList(a); } final List result = new ArrayList<>(a.length + b.length); final int lenA = a.length; final int lenB = b.length; int cursorA = 0; int cursorB = 0; while (cursorA < lenA || cursorB < lenB) { if ((cursorA < lenA) && ((cursorB >= lenB) || (nextSelector.apply(a[cursorA], b[cursorB]) == MergeResult.TAKE_FIRST))) { result.add(a[cursorA++]); } else { result.add(b[cursorB++]); } } return result; } /** * Merges two the input iterables into a list based where the order of the elements is determined by the given selector function. * * @param the type of elements in the iterables * @param a the first iterable to merge * @param b the second iterable to merge * @param nextSelector a function that determines the next element to add to the result list * @return a list containing the merged elements from both iterables. An empty list is returned if both iterables are {@code null} or empty. * @see #concat(Iterable, Iterable) */ public static List merge(final Iterable a, final Iterable b, final BiFunction nextSelector) { return merge(N.asList(a, b), nextSelector, Factory.ofList()); } /** * Merges multiple iterables into a list based where the order of the elements is determined by the given selector function. * * @param the type of elements in the iterables * @param c the collection of iterable to merge * @param nextSelector a function that determines the next element to add to the result list * @return a list containing the merged elements from all iterables. An empty list is returned if all iterables are {@code null} or empty. * @see #concat(Collection) * @see #concat(Collection, IntFunction) */ public static List merge(final Collection> c, final BiFunction nextSelector) { return merge(c, nextSelector, Factory.ofList()); } /** * Merges multiple iterables into a list based where the order of the elements is determined by the given selector function. * The returned collection is created by the specified {@code supplier}. * * @param the type of elements in the iterables * @param the type of the resulting collection * @param c the collection of iterable to merge * @param nextSelector a function that determines the next element to add to the result collection * @param supplier the supplier used to create the returned collection * @return a collection containing the merged elements from all iterables. An empty collection created by the specified {@code supplier} is returned if all iterables are {@code null} or empty. * @see #concat(Collection) * @see #concat(Collection, IntFunction) */ public static > C merge(final Collection> c, final BiFunction nextSelector, final IntFunction supplier) { if (isEmpty(c)) { return supplier.apply(0); } else if (c.size() == 1) { final Iterable a = N.firstOrNullIfEmpty(c); return a == null ? supplier.apply(0) : N.toCollection(a, supplier); } else if (c.size() == 2) { final Iterator> iter = c.iterator(); final Iterable a = iter.next(); final Iterable b = iter.next(); if (a == null) { return b == null ? supplier.apply(0) : N.toCollection(b, supplier); } else if (b == null) { return N.toCollection(a, supplier); } final C ret = supplier.apply(getSizeOrDefault(a, 0) + getSizeOrDefault(b, 0)); final Iterator iterA = a.iterator(); final Iterator iterB = b.iterator(); T nextA = null; T nextB = null; boolean hasNextA = false; boolean hasNextB = false; while (hasNextA || hasNextB || iterA.hasNext() || iterB.hasNext()) { if (hasNextA) { if (iterB.hasNext()) { if (nextSelector.apply(nextA, (nextB = iterB.next())) == MergeResult.TAKE_FIRST) { hasNextA = false; hasNextB = true; ret.add(nextA); } else { ret.add(nextB); } } else { hasNextA = false; ret.add(nextA); } } else if (hasNextB) { if (iterA.hasNext()) { if (nextSelector.apply((nextA = iterA.next()), nextB) == MergeResult.TAKE_FIRST) { ret.add(nextA); } else { hasNextA = true; hasNextB = false; ret.add(nextB); } } else { hasNextB = false; ret.add(nextB); } } else if (iterA.hasNext()) { if (iterB.hasNext()) { if (nextSelector.apply((nextA = iterA.next()), (nextB = iterB.next())) == MergeResult.TAKE_FIRST) { hasNextB = true; ret.add(nextA); } else { hasNextA = true; ret.add(nextB); } } else { ret.add(iterA.next()); } } else { ret.add(iterB.next()); } } return ret; } else { int totalSize = 0; Iterator mergedIter = ObjIterator.empty(); Iterator iter = null; for (final Iterable e : c) { iter = e == null ? null : e.iterator(); if (iter == null || !iter.hasNext()) { continue; } totalSize += getSizeOrDefault(e, 0); final Iterator iterA = mergedIter; final Iterator iterB = iter; mergedIter = new Iterator<>() { private T nextA = null; private T nextB = null; private boolean hasNextA = false; private boolean hasNextB = false; @Override public boolean hasNext() { return hasNextA || hasNextB || iterA.hasNext() || iterB.hasNext(); } @Override public T next() { if (hasNextA) { if (iterB.hasNext()) { if (nextSelector.apply(nextA, (nextB = iterB.next())) == MergeResult.TAKE_FIRST) { hasNextA = false; hasNextB = true; return nextA; } else { return nextB; } } else { hasNextA = false; return nextA; } } else if (hasNextB) { if (iterA.hasNext()) { if (nextSelector.apply((nextA = iterA.next()), nextB) == MergeResult.TAKE_FIRST) { return nextA; } else { hasNextA = true; hasNextB = false; return nextB; } } else { hasNextB = false; return nextB; } } else if (iterA.hasNext()) { if (iterB.hasNext()) { if (nextSelector.apply((nextA = iterA.next()), (nextB = iterB.next())) == MergeResult.TAKE_FIRST) { hasNextB = true; return nextA; } else { hasNextA = true; return nextB; } } else { return iterA.next(); } } else { return iterB.next(); } } }; } final C ret = supplier.apply(totalSize); while (mergedIter.hasNext()) { ret.add(mergedIter.next()); } return ret; } } // /** // * // * @param // * @param a // * @param b // * @param nextSelector // * @return // * @see {@code Iterators.merge(Iterator, Iterator, BiFunction)} // */ // public static List merge(final Iterator a, final Iterator b, // final Throwables.BiFunction nextSelector) throws E { // if (a == null) { // return b == null ? new ArrayList<>() : toList(b); // } else if (b == null) { // return toList(a); // } // // final List result = new ArrayList<>(9); // final Iterator iterA = a; // final Iterator iterB = b; // // T nextA = null; // T nextB = null; // boolean hasNextA = false; // boolean hasNextB = false; // // while (hasNextA || hasNextB || iterA.hasNext() || iterB.hasNext()) { // if (hasNextA) { // if (iterB.hasNext()) { // if (nextSelector.apply(nextA, (nextB = iterB.next())) == MergeResult.TAKE_FIRST) { // hasNextA = false; // hasNextB = true; // result.add(nextA); // } else { // result.add(nextB); // } // } else { // hasNextA = false; // result.add(nextA); // } // } else if (hasNextB) { // if (iterA.hasNext()) { // if (nextSelector.apply((nextA = iterA.next()), nextB) == MergeResult.TAKE_FIRST) { // result.add(nextA); // } else { // hasNextA = true; // hasNextB = false; // result.add(nextB); // } // } else { // hasNextB = false; // result.add(nextB); // } // } else if (iterA.hasNext()) { // if (iterB.hasNext()) { // if (nextSelector.apply((nextA = iterA.next()), (nextB = iterB.next())) == MergeResult.TAKE_FIRST) { // hasNextB = true; // result.add(nextA); // } else { // hasNextA = true; // result.add(nextB); // } // } else { // result.add(iterA.next()); // } // } else { // result.add(iterB.next()); // } // } // // return result; // } // /** // * // * @param // * @param // * @param // * @param a // * @param b // * @param zipFunction // * @return // * @see {@code Iterators.zip(Iterator, Iterator, BiFunction)} // */ // public static List zip(final Iterator a, final Iterator b, // final Throwables.BiFunction zipFunction) throws E { // if (a == null || b == null) { // return new ArrayList<>(); // } // // final Iterator iterA = a; // final Iterator iterB = b; // final List result = new ArrayList<>(9); // // while (iterA.hasNext() && iterB.hasNext()) { // result.add(zipFunction.apply(iterA.next(), iterB.next())); // } // // return result; // } // // /** // * // * @param // * @param // * @param // * @param // * @param a // * @param b // * @param c // * @param zipFunction // * @return // * @see {@code Iterators.zip(Iterator, Iterator, Iterator, TriFunction)} // */ // public static List zip(final Iterator a, final Iterator b, final Iterator c, // final Throwables.TriFunction zipFunction) throws E { // if (a == null || b == null || c == null) { // return new ArrayList<>(); // } // // final Iterator iterA = a; // final Iterator iterB = b; // final Iterator iterC = c; // final List result = new ArrayList<>(9); // // while (iterA.hasNext() && iterB.hasNext() && iterC.hasNext()) { // result.add(zipFunction.apply(iterA.next(), iterB.next(), iterC.next())); // } // // return result; // } // // /** // * // * @param // * @param // * @param // * @param a // * @param b // * @param valueForNoneA // * @param valueForNoneB // * @param zipFunction // * @return // * @see {@code Iterators.zip(Iterator, Iterator, Object, Object, BiFunction)} // */ // public static List zip(final Iterator a, final Iterator b, final A valueForNoneA, final B valueForNoneB, // final Throwables.BiFunction zipFunction) throws E { // final Iterator iterA = a == null ? ObjIterator. empty() : a; // final Iterator iterB = b == null ? ObjIterator. empty() : b; // // final List result = new ArrayList<>(9); // boolean hasA = true; // // do { // if (hasA && (hasA = iterA.hasNext())) { // result.add(zipFunction.apply(iterA.next(), iterB.hasNext() ? iterB.next() : valueForNoneB)); // } else if (iterB.hasNext()) { // result.add(zipFunction.apply(valueForNoneA, iterB.next())); // } else { // break; // } // } while (true); // // return result; // } // // /** // * // * @param // * @param // * @param // * @param // * @param a // * @param b // * @param c // * @param valueForNoneA // * @param valueForNoneB // * @param valueForNoneC // * @param zipFunction // * @return // * @see {@code Iterators.zip(Iterator, Iterator, Iterator, Object, Object, Object, TriFunction)} // */ // public static List zip(final Iterator a, final Iterator b, final Iterator c, final A valueForNoneA, // final B valueForNoneB, final C valueForNoneC, final Throwables.TriFunction zipFunction) throws E { // final Iterator iterA = a == null ? ObjIterator. empty() : a; // final Iterator iterB = b == null ? ObjIterator. empty() : b; // final Iterator iterC = c == null ? ObjIterator. empty() : c; // // final List result = new ArrayList<>(9); // boolean hasA = true; // boolean hasB = true; // // do { // if (hasA && (hasA = iterA.hasNext())) { // result.add(zipFunction.apply(iterA.next(), iterB.hasNext() ? iterB.next() : valueForNoneB, iterC.hasNext() ? iterC.next() : valueForNoneC)); // } else if (hasB && (hasB = iterB.hasNext())) { // result.add(zipFunction.apply(valueForNoneA, iterB.next(), iterC.hasNext() ? iterC.next() : valueForNoneC)); // } else if (iterC.hasNext()) { // result.add(zipFunction.apply(valueForNoneA, valueForNoneB, iterC.hasNext() ? iterC.next() : valueForNoneC)); // } else { // break; // } // } while (true); // // return result; // } // /** // * // * @param // * @param // * @param // * @param iter // * @param unzip the second parameter is an output parameter. // * @return // * @see {@code Iterators.unzip(Iterator, BiConsumer)} // */ // public static Pair, List> unzip(final Iterator iter, // final Throwables.BiConsumer, E> unzip) throws E { // final int len = 9; // // final List l = new ArrayList<>(len); // final List r = new ArrayList<>(len); // final Pair p = new Pair<>(); // // if (iter != null) { // T e = null; // // while (iter.hasNext()) { // e = iter.next(); // // unzip.accept(e, p); // // l.add(p.left); // r.add(p.right); // } // } // // return Pair.of(l, r); // } /** * Zips two arrays into a single list using the provided zip function. * The size of the resulting list is equal to the size of the shorter input array. * * @param the type of elements in the first array * @param the type of elements in the second array * @param the type of elements in the resulting list * @param a the first array to zip * @param b the second array to zip * @param zipFunction a function that combines elements from the two arrays. An empty list is returned if the one of input arrays is {@code null} or empty. * @return a list containing the zipped elements * @see Fn#pair() * @see Fn#tuple2() */ public static List zip(final A[] a, final B[] b, final BiFunction zipFunction) { if (isEmpty(a) || isEmpty(b)) { return new ArrayList<>(); } final int minLen = min(a.length, b.length); final List result = new ArrayList<>(minLen); for (int i = 0; i < minLen; i++) { result.add(zipFunction.apply(a[i], b[i])); } return result; } /** * Zips two iterables into a single list using the provided zip function. * The size of the resulting list is equal to the size of the shorter input iterable. * * @param the type of elements in the first iterable * @param the type of elements in the second iterable * @param the type of elements in the resulting list * @param a the first iterable to zip * @param b the second iterable to zip * @param zipFunction a function that combines elements from the two iterables. An empty list is returned if the one of input iterables is {@code null} or empty. * @return a list containing the zipped elements * @see Fn#pair() * @see Fn#tuple2() */ public static List zip(final Iterable a, final Iterable b, final BiFunction zipFunction) { if (isEmptyCollection(a) || isEmptyCollection(b)) { return new ArrayList<>(); } final Iterator iterA = a.iterator(); final Iterator iterB = b.iterator(); final int minLen = min(getSizeOrDefault(a, 0), getSizeOrDefault(b, 0)); final List result = new ArrayList<>(minLen); while (iterA.hasNext() && iterB.hasNext()) { result.add(zipFunction.apply(iterA.next(), iterB.next())); } return result; } /** * Zips three arrays into a single list using the provided zip function. * The size of the resulting list is equal to the size of the shortest input array. * * @param the type of elements in the first array * @param the type of elements in the second array * @param the type of elements in the third array * @param the type of elements in the resulting list * @param a the first array to zip * @param b the second array to zip * @param c the third array to zip * @param zipFunction a function that combines elements from the three arrays. An empty list is returned if the one of input arrays is {@code null} or empty. * @return a list containing the zipped elements * @see Fn#triple() * @see Fn#tuple3() */ public static List zip(final A[] a, final B[] b, final C[] c, final TriFunction zipFunction) { if (isEmpty(a) || isEmpty(b) || isEmpty(c)) { return new ArrayList<>(); } final int minLen = min(a.length, b.length, c.length); final List result = new ArrayList<>(minLen); for (int i = 0; i < minLen; i++) { result.add(zipFunction.apply(a[i], b[i], c[i])); } return result; } /** * Zips three iterables into a single list using the provided zip function. * The size of the resulting list is equal to the size of the shortest input iterables. * * @param the type of elements in the first iterable * @param the type of elements in the second iterable * @param the type of elements in the third iterable * @param the type of elements in the resulting list * @param a the first iterable to zip * @param b the second iterable to zip * @param c the third iterable to zip * @param zipFunction a function that combines elements from the three iterables. An empty list is returned if the one of input iterables is {@code null} or empty. * @return a list containing the zipped elements * @see Fn#triple() * @see Fn#tuple3() */ public static List zip(final Iterable a, final Iterable b, final Iterable c, final TriFunction zipFunction) { if (isEmptyCollection(a) || isEmptyCollection(b) || isEmptyCollection(c)) { return new ArrayList<>(); } final Iterator iterA = a.iterator(); final Iterator iterB = b.iterator(); final Iterator iterC = c.iterator(); final int minLen = min(getSizeOrDefault(a, 0), getSizeOrDefault(b, 0), getSizeOrDefault(c, 0)); final List result = new ArrayList<>(minLen); while (iterA.hasNext() && iterB.hasNext() && iterC.hasNext()) { result.add(zipFunction.apply(iterA.next(), iterB.next(), iterC.next())); } return result; } /** * Zips two arrays into a single list using the provided zip function. * If one array is shorter, the provided default values are used for the remaining elements. * The size of the resulting list is equal to the size of the longer input array. * * @param the type of elements in the first array * @param the type of elements in the second array * @param the type of elements in the resulting list * @param a the first array to zip * @param b the second array to zip * @param valueForNoneA the default value to use if the first array is shorter * @param valueForNoneB the default value to use if the second array is shorter * @param zipFunction a function that combines elements from the two arrays * @return a list containing the zipped elements * @see Fn#pair() * @see Fn#tuple2() */ public static List zip(final A[] a, final B[] b, final A valueForNoneA, final B valueForNoneB, final BiFunction zipFunction) { final int lenA = len(a); final int lenB = len(b); final int maxLen = max(lenA, lenB); final List result = new ArrayList<>(maxLen); for (int i = 0; i < maxLen; i++) { result.add(zipFunction.apply(i < lenA ? a[i] : valueForNoneA, i < lenB ? b[i] : valueForNoneB)); } return result; } /** * Zips two iterables into a single list using the provided zip function. * If one iterable is shorter, the provided default values are used for the remaining elements. * The size of the resulting list is equal to the size of the longer input iterable. * * @param the type of elements in the first iterable * @param the type of elements in the second iterable * @param the type of elements in the resulting list * @param a the first iterable to zip * @param b the second iterable to zip * @param valueForNoneA the default value to use if the first iterable is shorter * @param valueForNoneB the default value to use if the second iterable is shorter * @param zipFunction a function that combines elements from the two iterables * @return a list containing the zipped elements * @see Fn#pair() * @see Fn#tuple2() */ public static List zip(final Iterable a, final Iterable b, final A valueForNoneA, final B valueForNoneB, final BiFunction zipFunction) { final Iterator iterA = a == null ? ObjIterator.empty() : a.iterator(); final Iterator iterB = b == null ? ObjIterator.empty() : b.iterator(); final int lenA = getSizeOrDefault(a, 0); final int lenB = getSizeOrDefault(b, 0); final int maxLen = max(lenA, lenB); final List result = new ArrayList<>(maxLen); if (a == null || a instanceof Collection) { if (b == null || b instanceof Collection) { for (int i = 0; i < maxLen; i++) { result.add(zipFunction.apply(i < lenA ? iterA.next() : valueForNoneA, i < lenB ? iterB.next() : valueForNoneB)); } } else { for (int i = 0; i < lenA || iterB.hasNext(); i++) { result.add(zipFunction.apply(i < lenA ? iterA.next() : valueForNoneA, iterB.hasNext() ? iterB.next() : valueForNoneB)); } } } else if (b == null || b instanceof Collection) { for (int i = 0; i < lenB || iterA.hasNext(); i++) { result.add(zipFunction.apply(iterA.hasNext() ? iterA.next() : valueForNoneA, i < lenB ? iterB.next() : valueForNoneB)); } } else { while (iterA.hasNext() || iterB.hasNext()) { result.add(zipFunction.apply(iterA.hasNext() ? iterA.next() : valueForNoneA, iterB.hasNext() ? iterB.next() : valueForNoneB)); } } return result; } /** * Zips three arrays into a single list using the provided zip function. * If one array is shorter, the provided default values are used for the remaining elements. * The size of the resulting list is equal to the size of the longest input array. * * @param the type of elements in the first array * @param the type of elements in the second array * @param the type of elements in the third array * @param the type of elements in the resulting list * @param a the first array to zip * @param b the second array to zip * @param c the third array to zip * @param valueForNoneA the default value to use if the first array is shorter * @param valueForNoneB the default value to use if the second array is shorter * @param valueForNoneC the default value to use if the third array is shorter * @param zipFunction a function that combines elements from the three arrays * @return a list containing the zipped elements * @see Fn#triple() * @see Fn#tuple3() */ public static List zip(final A[] a, final B[] b, final C[] c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final TriFunction zipFunction) { final int lenA = len(a); final int lenB = len(b); final int lenC = len(c); final int maxLen = max(lenA, lenB, lenC); final List result = new ArrayList<>(maxLen); for (int i = 0; i < maxLen; i++) { result.add(zipFunction.apply(i < lenA ? a[i] : valueForNoneA, i < lenB ? b[i] : valueForNoneB, i < lenC ? c[i] : valueForNoneC)); } return result; } /** * Zips three iterables into a single list using the provided zip function. * If one iterable is shorter, the provided default values are used for the remaining elements. * The size of the resulting list is equal to the size of the longest input iterable. * * @param the type of elements in the first iterable * @param the type of elements in the second iterable * @param the type of elements in the third iterable * @param the type of elements in the resulting list * @param a the first iterable to zip * @param b the second iterable to zip * @param c the third iterable to zip * @param valueForNoneA the default value to use if the first iterable is shorter * @param valueForNoneB the default value to use if the second iterable is shorter * @param valueForNoneC the default value to use if the third iterable is shorter * @param zipFunction a function that combines elements from the three iterables * @return a list containing the zipped elements * @see Fn#triple() * @see Fn#tuple3() */ public static List zip(final Iterable a, final Iterable b, final Iterable c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final TriFunction zipFunction) { final Iterator iterA = isEmptyCollection(a) ? ObjIterator.empty() : a.iterator(); final Iterator iterB = isEmptyCollection(b) ? ObjIterator.empty() : b.iterator(); final Iterator iterC = isEmptyCollection(c) ? ObjIterator.empty() : c.iterator(); final int lenA = getSizeOrDefault(a, 0); final int lenB = getSizeOrDefault(b, 0); final int lenC = getSizeOrDefault(c, 0); final int maxLen = max(lenA, lenB, lenC); final List result = new ArrayList<>(maxLen); if (a == null || a instanceof Collection) { if (b == null || b instanceof Collection) { if (c == null || c instanceof Collection) { for (int i = 0; i < maxLen; i++) { result.add(zipFunction.apply(i < lenA ? iterA.next() : valueForNoneA, i < lenB ? iterB.next() : valueForNoneB, i < lenC ? iterC.next() : valueForNoneC)); } } else { for (int i = 0; i < lenA || i < lenB || iterC.hasNext(); i++) { result.add(zipFunction.apply(i < lenA ? iterA.next() : valueForNoneA, i < lenB ? iterB.next() : valueForNoneB, iterC.hasNext() ? iterC.next() : valueForNoneC)); } } } else { if (c == null || c instanceof Collection) { for (int i = 0; i < lenA || i < lenC || iterB.hasNext(); i++) { result.add(zipFunction.apply(i < lenA ? iterA.next() : valueForNoneA, iterB.hasNext() ? iterB.next() : valueForNoneB, i < lenC ? iterC.next() : valueForNoneC)); } } else { for (int i = 0; i < lenA || iterB.hasNext() || iterC.hasNext(); i++) { result.add(zipFunction.apply(i < lenA ? iterA.next() : valueForNoneA, iterB.hasNext() ? iterB.next() : valueForNoneB, iterC.hasNext() ? iterC.next() : valueForNoneC)); } } } } else if (b == null || b instanceof Collection) { if (c == null || c instanceof Collection) { for (int i = 0; i < lenB || i < lenC || iterA.hasNext(); i++) { result.add(zipFunction.apply(iterA.hasNext() ? iterA.next() : valueForNoneA, i < lenB ? iterB.next() : valueForNoneB, i < lenC ? iterC.next() : valueForNoneC)); } } else { for (int i = 0; i < lenB || iterA.hasNext() || iterC.hasNext(); i++) { result.add(zipFunction.apply(iterA.hasNext() ? iterA.next() : valueForNoneA, i < lenB ? iterB.next() : valueForNoneB, iterC.hasNext() ? iterC.next() : valueForNoneC)); } } } else { if (c == null || c instanceof Collection) { for (int i = 0; i < lenC || iterA.hasNext() || iterB.hasNext(); i++) { result.add(zipFunction.apply(iterA.hasNext() ? iterA.next() : valueForNoneA, iterB.hasNext() ? iterB.next() : valueForNoneB, i < lenC ? iterC.next() : valueForNoneC)); } } else { while (iterA.hasNext() || iterB.hasNext() || iterC.hasNext()) { result.add(zipFunction.apply(iterA.hasNext() ? iterA.next() : valueForNoneA, iterB.hasNext() ? iterB.next() : valueForNoneB, iterC.hasNext() ? iterC.next() : valueForNoneC)); } } } return result; } // /** // * // * @param // * @param // * @param // * @param a // * @param b // * @param zipFunction // * @return // * @see {@code Iterators.zip(Iterator, Iterator, BiFunction)} // */ // public static List zip(final Iterator a, final Iterator b, // final BiFunction zipFunction) { // if (a == null || b == null) { // return new ArrayList<>(); // } // // final Iterator iterA = a; // final Iterator iterB = b; // final List result = new ArrayList<>(9); // // while (iterA.hasNext() && iterB.hasNext()) { // result.add(zipFunction.apply(iterA.next(), iterB.next())); // } // // return result; // } // // /** // * // * @param // * @param // * @param // * @param // * @param a // * @param b // * @param c // * @param zipFunction // * @return // * @see {@code Iterators.zip(Iterator, Iterator, Iterator, TriFunction)} // */ // public static List zip(final Iterator a, final Iterator b, final Iterator c, // final TriFunction zipFunction) { // if (a == null || b == null || c == null) { // return new ArrayList<>(); // } // // final Iterator iterA = a; // final Iterator iterB = b; // final Iterator iterC = c; // final List result = new ArrayList<>(9); // // while (iterA.hasNext() && iterB.hasNext() && iterC.hasNext()) { // result.add(zipFunction.apply(iterA.next(), iterB.next(), iterC.next())); // } // // return result; // } // // /** // * // * @param // * @param // * @param // * @param a // * @param b // * @param valueForNoneA // * @param valueForNoneB // * @param zipFunction // * @return // * @see {@code Iterators.zip(Iterator, Iterator, Object, Object, BiFunction)} // */ // public static List zip(final Iterator a, final Iterator b, final A valueForNoneA, final B valueForNoneB, // final BiFunction zipFunction) { // final Iterator iterA = a == null ? ObjIterator. empty() : a; // final Iterator iterB = b == null ? ObjIterator. empty() : b; // // final List result = new ArrayList<>(9); // boolean hasA = true; // // do { // if (hasA && (hasA = iterA.hasNext())) { // result.add(zipFunction.apply(iterA.next(), iterB.hasNext() ? iterB.next() : valueForNoneB)); // } else if (iterB.hasNext()) { // result.add(zipFunction.apply(valueForNoneA, iterB.next())); // } else { // break; // } // } while (true); // // return result; // } // // /** // * // * @param // * @param // * @param // * @param // * @param a // * @param b // * @param c // * @param valueForNoneA // * @param valueForNoneB // * @param valueForNoneC // * @param zipFunction // * @return // * @see {@code Iterators.zip(Iterator, Iterator, Iterator, Object, Object, Object, TriFunction)} // */ // public static List zip(final Iterator a, final Iterator b, final Iterator c, final A valueForNoneA, // final B valueForNoneB, final C valueForNoneC, final TriFunction zipFunction) { // final Iterator iterA = a == null ? ObjIterator. empty() : a; // final Iterator iterB = b == null ? ObjIterator. empty() : b; // final Iterator iterC = c == null ? ObjIterator. empty() : c; // // final List result = new ArrayList<>(9); // boolean hasA = true; // boolean hasB = true; // // do { // if (hasA && (hasA = iterA.hasNext())) { // result.add(zipFunction.apply(iterA.next(), iterB.hasNext() ? iterB.next() : valueForNoneB, iterC.hasNext() ? iterC.next() : valueForNoneC)); // } else if (hasB && (hasB = iterB.hasNext())) { // result.add(zipFunction.apply(valueForNoneA, iterB.next(), iterC.hasNext() ? iterC.next() : valueForNoneC)); // } else if (iterC.hasNext()) { // result.add(zipFunction.apply(valueForNoneA, valueForNoneB, iterC.hasNext() ? iterC.next() : valueForNoneC)); // } else { // break; // } // } while (true); // // return result; // } /** * Zips two arrays into a single array using the provided zip function. * The size of the resulting array is equal to the size of the shorter input array. * * @param the type of elements in the first array * @param the type of elements in the second array * @param the type of elements in the resulting array * @param a the first array to zip * @param b the second array to zip * @param targetElementType the class of the resulting array's element type * @param zipFunction a function that combines elements from the two arrays. An empty list is returned if the one of input arrays is {@code null} or empty. * @return an array containing the zipped elements * @throws IllegalArgumentException if the targetElementType is null */ public static R[] zip(final A[] a, final B[] b, final BiFunction zipFunction, final Class targetElementType) throws IllegalArgumentException { final int lenA = len(a); final int lenB = len(b); final int minLen = min(lenA, lenB); final R[] result = newArray(targetElementType, minLen); for (int i = 0; i < minLen; i++) { result[i] = zipFunction.apply(a[i], b[i]); } return result; } /** * Zips two arrays into a single array using the provided zip function. * If one array is shorter, the provided default values are used for the remaining elements. * The size of the resulting array is equal to the size of the longer input array. * * @param the type of elements in the first array * @param the type of elements in the second array * @param the type of elements in the resulting array * @param a the first array to zip * @param b the second array to zip * @param valueForNoneA the default value to use if the first array is shorter * @param valueForNoneB the default value to use if the second array is shorter * @param targetElementType the class of the resulting array's element type * @param zipFunction a function that combines elements from the two arrays * @return an array containing the zipped elements * @throws IllegalArgumentException if the targetElementType is null */ public static R[] zip(final A[] a, final B[] b, final A valueForNoneA, final B valueForNoneB, final BiFunction zipFunction, final Class targetElementType) throws IllegalArgumentException { final int lenA = len(a); final int lenB = len(b); final int minLen = min(lenA, lenB); final int maxLen = max(lenA, lenB); final R[] result = newArray(targetElementType, maxLen); for (int i = 0; i < minLen; i++) { result[i] = zipFunction.apply(a[i], b[i]); } if (lenA < maxLen) { for (int i = lenA; i < maxLen; i++) { result[i] = zipFunction.apply(valueForNoneA, b[i]); } } else if (lenB < maxLen) { for (int i = lenB; i < maxLen; i++) { result[i] = zipFunction.apply(a[i], valueForNoneB); } } return result; } /** * Zips three arrays into a single array using the provided zip function. * The size of the resulting array is equal to the size of the shortest input array. * * @param the type of elements in the first array * @param the type of elements in the second array * @param the type of elements in the third array * @param the type of elements in the resulting array * @param a the first array to zip * @param b the second array to zip * @param c the third array to zip * @param targetElementType the class of the resulting array's element type * @param zipFunction a function that combines elements from the three arrays. An empty list is returned if the one of input arrays is {@code null} or empty. * @return an array containing the zipped elements * @throws IllegalArgumentException if the targetElementType is null */ public static R[] zip(final A[] a, final B[] b, final C[] c, final TriFunction zipFunction, final Class targetElementType) throws IllegalArgumentException { final int lenA = len(a); final int lenB = len(b); final int lenC = len(c); final int minLen = min(lenA, lenB, lenC); final R[] result = newArray(targetElementType, minLen); for (int i = 0; i < minLen; i++) { result[i] = zipFunction.apply(a[i], b[i], c[i]); } return result; } /** * Zips three arrays into a single array using the provided zip function. * If one array is shorter, the provided default values are used for the remaining elements. * The size of the resulting array is equal to the size of the longest input array. * * @param the type of elements in the first array * @param the type of elements in the second array * @param the type of elements in the third array * @param the type of elements in the resulting array * @param a the first array to zip * @param b the second array to zip * @param c the third array to zip * @param valueForNoneA the default value to use if the first array is shorter * @param valueForNoneB the default value to use if the second array is shorter * @param valueForNoneC the default value to use if the third array is shorter * @param targetElementType the class of the resulting array's element type * @param zipFunction a function that combines elements from the three arrays * @return an array containing the zipped elements * @throws IllegalArgumentException if the targetElementType is null */ public static R[] zip(final A[] a, final B[] b, final C[] c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final TriFunction zipFunction, final Class targetElementType) throws IllegalArgumentException { final int lenA = len(a); final int lenB = len(b); final int lenC = len(c); final int minLen = min(lenA, lenB, lenC); final int maxLen = max(lenA, lenB, lenC); final R[] result = newArray(targetElementType, maxLen); for (int i = 0; i < minLen; i++) { result[i] = zipFunction.apply(a[i], b[i], c[i]); } if (minLen < maxLen) { for (int i = minLen; i < maxLen; i++) { result[i] = zipFunction.apply(i < lenA ? a[i] : valueForNoneA, i < lenB ? b[i] : valueForNoneB, i < lenC ? c[i] : valueForNoneC); } } return result; } /** * Unzips an iterable into two separate lists using the provided unzip function. * * @param the type of elements in the input iterable * @param the type of elements in the first output list * @param the type of elements in the second output list * @param c the input iterable to unzip * @param unzip a function that takes an element from the input iterable and a pair, and populates the pair with the unzipped values * @return a pair of lists, where the first list contains the first elements and the second list contains the second elements */ public static Pair, List> unzip(final Iterable c, final BiConsumer> unzip) { return unzip(c, unzip, Factory.ofList()); } /** * Unzips an iterable into two separate collections using the provided unzip function. * * @param the type of elements in the input iterable * @param the type of elements in the first output collection * @param the type of elements in the second output collection * @param the type of the first output collection * @param the type of the second output collection * @param c the input iterable to unzip * @param unzip a function that takes an element from the input iterable and a pair, and populates the pair with the unzipped values * @param supplier a function that provides new instances of the output collections * @return a pair of lists, where the first collection contains the first elements and the second collection contains the second elements */ public static , RC extends Collection> Pair unzip(final Iterable c, final BiConsumer> unzip, final IntFunction> supplier) { final int len = getSizeOrDefault(c, 0); final LC l = (LC) supplier.apply(len); final RC r = (RC) supplier.apply(len); final Pair p = new Pair<>(); if (c != null) { for (final T e : c) { unzip.accept(e, p); l.add(p.left); r.add(p.right); } } return Pair.of(l, r); } // /** // * // * @param // * @param // * @param // * @param iter // * @param unzip the second parameter is an output parameter. // * @return // * @see {@code Iterators.unzip(Iterator, BiConsumer)} // */ // public static Pair, List> unzip(final Iterator iter, // final BiConsumer> unzip) { // final int len = 9; // // final List l = new ArrayList<>(len); // final List r = new ArrayList<>(len); // final Pair p = new Pair<>(); // // if (iter != null) { // T e = null; // // while (iter.hasNext()) { // e = iter.next(); // // unzip.accept(e, p); // // l.add(p.left); // r.add(p.right); // } // } // // return Pair.of(l, r); // } /** * Unzips an iterable into three separate lists using the provided unzip function. * * @param the type of elements in the input iterable * @param the type of elements in the first output list * @param the type of elements in the second output list * @param the type of elements in the third output list * @param c the input iterable to unzip * @param unzip a function that takes an element from the input iterable and a triple, and populates the triple with the unzipped values * @return a triple of lists, where the first list contains the first elements, the second list contains the second elements and the third list contains the third elements * @see TriIterator#unzip(Iterable, BiConsumer) * @see TriIterator#toMultiList(Supplier) * @see TriIterator#toMultiSet(Supplier) * @deprecated replaced by {@link TriIterator#unzip(Iterable, BiConsumer)} */ @Deprecated public static Triple, List, List> unzipp(final Iterable c, final BiConsumer> unzip) { return unzipp(c, unzip, Factory.ofList()); } /** * Unzips an iterable into three separate collections using the provided unzip function. * * @param the type of elements in the input iterable * @param the type of elements in the first output collection * @param the type of elements in the second output collection * @param the type of elements in the third output collection * @param the type of the first output collection * @param the type of the second output collection * @param the type of the third output collection * @param c the input iterable to unzip * @param unzip a function that takes an element from the input iterable and a triple, and populates the triple with the unzipped values * @param supplier a function that provides new instances of the output collections * @return a triple of collections, where the first collection contains the first elements, the second collection contains the second elements and the third collection contains the third elements * @see TriIterator#unzip(Iterable, BiConsumer) * @see TriIterator#toMultiList(Supplier) * @see TriIterator#toMultiSet(Supplier) * @deprecated replaced by {@link TriIterator#unzip(Iterable, BiConsumer)} */ @Deprecated public static , MC extends Collection, RC extends Collection> Triple unzipp( final Iterable c, final BiConsumer> unzip, final IntFunction> supplier) { final int len = getSizeOrDefault(c, 0); final LC l = (LC) supplier.apply(len); final MC m = (MC) supplier.apply(len); final RC r = (RC) supplier.apply(len); final Triple t = new Triple<>(); if (c != null) { for (final T e : c) { unzip.accept(e, t); l.add(t.left); m.add(t.middle); r.add(t.right); } } return Triple.of(l, m, r); } /** * Groups the elements in the given array by the key extracted by the specified {@code Function}. * * @param the type of elements in the array * @param the type of keys * @param a the array to group * @param keyExtractor a function to extract the key for grouping * @return a map where the keys are extracted from the elements and the values are lists of elements that share the same key. An empty map is returned if the input array is {@code null} or empty. */ @Beta public static Map> groupBy(final T[] a, final Function keyExtractor) { return groupBy(a, keyExtractor, Suppliers.ofMap()); } /** * Groups the elements in the given array by the key extracted by the specified {@code Function}. * * @param the type of elements in the array * @param the type of keys * @param the type of returned map * @param a the array to group * @param keyExtractor a function to extract the key for grouping * @param mapSupplier a function to create the returned map * @return a map where the keys are extracted from the elements and the values are lists of elements that share the same key. An empty map is returned if the input array is {@code null} or empty. */ @Beta public static >> M groupBy(final T[] a, final Function keyExtractor, final Supplier mapSupplier) { return groupBy(a, 0, len(a), keyExtractor, mapSupplier); } /** * Groups the elements within specified range in the given array by the key extracted by the specified {@code Function}. * * @param the type of elements in the array * @param the type of keys * @param a the array to group * @param fromIndex the index of the first element (inclusive) to be grouped * @param toIndex the index of the last element (exclusive) to be grouped * @param keyExtractor a function to extract the key for grouping * @return a map where the keys are extracted from the elements within specified range and the values are lists of elements that share the same key. An empty map is returned if the input array is {@code null} or empty. * @throws IndexOutOfBoundsException if the specified range is out of bounds */ @Beta public static Map> groupBy(final T[] a, final int fromIndex, final int toIndex, final Function keyExtractor) { return groupBy(a, fromIndex, toIndex, keyExtractor, Suppliers.ofMap()); } /** * Groups the elements within specified range in the given array by the key extracted by the specified {@code Function}. * * @param the type of elements in the array * @param the type of keys * @param the type of returned map * @param a the array to group * @param fromIndex the index of the first element (inclusive) to be grouped * @param toIndex the index of the last element (exclusive) to be grouped * @param keyExtractor a function to extract the key for grouping * @param mapSupplier a function to create the returned map * @return a map where the keys are extracted from the elements within specified range and the values are lists of elements that share the same key. An empty map is returned if the input array is {@code null} or empty. * @throws IndexOutOfBoundsException if the specified range is out of bounds */ @Beta public static >> M groupBy(final T[] a, final int fromIndex, final int toIndex, final Function keyExtractor, final Supplier mapSupplier) throws IndexOutOfBoundsException { final int length = len(a); checkFromToIndex(fromIndex, toIndex, length); final M ret = mapSupplier.get(); K key = null; List val = null; for (int i = fromIndex; i < toIndex; i++) { key = keyExtractor.apply(a[i]); val = ret.computeIfAbsent(key, k -> new ArrayList<>()); val.add(a[i]); } return ret; } /** * Groups the elements within specified range in the given collection by the key extracted by the specified {@code Function}. * * @param the type of elements in the collection * @param the type of keys * @param c the collection to group * @param fromIndex the index of the first element (inclusive) to be grouped * @param toIndex the index of the last element (exclusive) to be grouped * @param keyExtractor a function to extract the key for grouping * @return a map where the keys are extracted from the elements within specified range and the values are lists of elements that share the same key. An empty map is returned if the input collection is {@code null} or empty. * @throws IndexOutOfBoundsException if the specified range is out of bounds */ @Beta public static Map> groupBy(final Collection c, final int fromIndex, final int toIndex, final Function keyExtractor) { return groupBy(c, fromIndex, toIndex, keyExtractor, Suppliers.ofMap()); } /** * Groups the elements within specified range in the given collection by the key extracted by the specified {@code Function}. * * @param the type of elements in the collection * @param the type of keys * @param the type of returned map * @param c the collection to group * @param fromIndex the index of the first element (inclusive) to be grouped * @param toIndex the index of the last element (exclusive) to be grouped * @param keyExtractor a function to extract the key for grouping * @param mapSupplier a function to create the returned map * @return a map where the keys are extracted from the elements within specified range and the values are lists of elements that share the same key. An empty map is returned if the collection array is {@code null} or empty. * @throws IndexOutOfBoundsException if the specified range is out of bounds */ @Beta public static >> M groupBy(final Collection c, final int fromIndex, final int toIndex, final Function keyExtractor, final Supplier mapSupplier) throws IndexOutOfBoundsException { final int length = size(c); checkFromToIndex(fromIndex, toIndex, length); final M ret = mapSupplier.get(); K key = null; List val = null; if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; T e = null; for (int i = fromIndex; i < toIndex; i++) { e = list.get(i); key = keyExtractor.apply(e); val = ret.computeIfAbsent(key, k -> new ArrayList<>()); val.add(e); } } else { int idx = 0; for (final T e : c) { if (idx++ < fromIndex) { continue; } key = keyExtractor.apply(e); val = ret.computeIfAbsent(key, k -> new ArrayList<>()); val.add(e); if (idx >= toIndex) { break; } } } return ret; } /** * Groups the elements in the given iterable by the key extracted by the specified {@code Function}. * * @param the type of elements in the iterable * @param the type of keys * @param c the iterable to group * @param keyExtractor a function to extract the key for grouping * @return a map where the keys are extracted from the elements and the values are lists of elements that share the same key. An empty map is returned if the input iterable is {@code null} or empty. */ @Beta public static Map> groupBy(final Iterable c, final Function keyExtractor) { return groupBy(c, keyExtractor, Suppliers.ofMap()); } /** * Groups the elements in the given iterable by the key extracted by the specified {@code Function}. * * @param the type of elements in the iterable * @param the type of keys * @param the type of returned map * @param c the iterable to group * @param keyExtractor a function to extract the key for grouping * @param mapSupplier a function to create the returned map * @return a map where the keys are extracted from the elements and the values are lists of elements that share the same key. An empty map is returned if the input iterable is {@code null} or empty. */ @Beta public static >> M groupBy(final Iterable c, final Function keyExtractor, final Supplier mapSupplier) { final M ret = mapSupplier.get(); if (c == null) { return ret; } K key = null; List val = null; for (final T e : c) { key = keyExtractor.apply(e); val = ret.computeIfAbsent(key, k -> new ArrayList<>()); val.add(e); } return ret; } /** * Groups the elements in the given iterator by the key extracted by the specified {@code Function}. * * @param the type of elements in the iterator * @param the type of keys * @param iter the iterator to group * @param keyExtractor a function to extract the key for grouping * @return a map where the keys are extracted from the elements and the values are lists of elements that share the same key. An empty map is returned if the input iterator is {@code null} or empty. */ @Beta public static Map> groupBy(final Iterator iter, final Function keyExtractor) { return groupBy(iter, keyExtractor, Suppliers.ofMap()); } /** * Groups the elements in the given iterator by the key extracted by the specified {@code Function}. * * @param the type of elements in the iterator * @param the type of keys * @param the type of returned map * @param iter the iterator to group * @param keyExtractor a function to extract the key for grouping * @param mapSupplier a function to create the returned map * @return a map where the keys are extracted from the elements and the values are lists of elements that share the same key. An empty map is returned if the input iterator is {@code null} or empty. */ @Beta public static >> M groupBy(final Iterator iter, final Function keyExtractor, final Supplier mapSupplier) { final M ret = mapSupplier.get(); if (iter == null) { return ret; } K key = null; List val = null; T e = null; while (iter.hasNext()) { e = iter.next(); key = keyExtractor.apply(e); val = ret.computeIfAbsent(key, k -> new ArrayList<>()); val.add(e); } return ret; } /** * Groups the elements in the given iterable by the key extracted by the specified {@code Function}. * The values in the resulting map are lists of elements transformed by the value extractor function. * * @param the type of elements in the input iterable * @param the type of keys * @param the type of values in the resulting lists * @param c the input iterable to group * @param keyExtractor a function to extract the key for grouping * @param valueExtractor a function to extract the value for the resulting lists * @return a map where the keys are extracted from the elements and the values are lists of elements transformed by the value extractor function. An empty map is returned if the input iterable is {@code null} or empty. */ @Beta public static Map> groupBy(final Iterable c, final Function keyExtractor, final Function valueExtractor) { return groupBy(c, keyExtractor, valueExtractor, Suppliers.ofMap()); } /** * Groups the elements in the given iterable by the key extracted by the specified {@code Function}. * The values in the resulting map are lists of elements transformed by the value extractor function. * * @param the type of elements in the input iterable * @param the type of keys * @param the type of values in the resulting lists * @param the type of returned map * @param c the input iterable to group * @param keyExtractor a function to extract the key for grouping * @param valueExtractor a function to extract the value for the resulting lists * @param mapSupplier a function to create the returned map * @return a map where the keys are extracted from the elements and the values are lists of elements transformed by the value extractor function. An empty map is returned if the input iterable is {@code null} or empty. */ @Beta public static >> M groupBy(final Iterable c, final Function keyExtractor, final Function valueExtractor, final Supplier mapSupplier) { final M ret = mapSupplier.get(); if (c == null) { return ret; } K key = null; List val = null; for (final T e : c) { key = keyExtractor.apply(e); val = ret.computeIfAbsent(key, k -> new ArrayList<>()); val.add(valueExtractor.apply(e)); } return ret; } /** * Groups the elements in the given iterator by the key extracted by the specified {@code Function}. * The values in the resulting map are lists of elements transformed by the value extractor function. * * @param the type of elements in the input iterator * @param the type of keys * @param the type of values in the resulting lists * @param iter the input iterator to group * @param keyExtractor a function to extract the key for grouping * @param valueExtractor a function to extract the value for the resulting lists * @return a map where the keys are extracted from the elements and the values are lists of elements transformed by the value extractor function. An empty map is returned if the input iterator is {@code null} or empty. */ @Beta public static Map> groupBy(final Iterator iter, final Function keyExtractor, final Function valueExtractor) { return groupBy(iter, keyExtractor, valueExtractor, Suppliers.ofMap()); } /** * Groups the elements in the given iterator by the key extracted by the specified {@code Function}. * The values in the resulting map are lists of elements transformed by the value extractor function. * * @param the type of elements in the input iterator * @param the type of keys * @param the type of values in the resulting lists * @param the type of returned map * @param iter the input iterator to group * @param keyExtractor a function to extract the key for grouping * @param valueExtractor a function to extract the value for the resulting lists * @param mapSupplier a function to create the returned map * @return a map where the keys are extracted from the elements and the values are lists of elements transformed by the value extractor function. An empty map is returned if the input iterator is {@code null} or empty. */ @Beta public static >> M groupBy(final Iterator iter, final Function keyExtractor, final Function valueExtractor, final Supplier mapSupplier) { final M ret = mapSupplier.get(); if (iter == null) { return ret; } K key = null; List val = null; T e = null; while (iter.hasNext()) { e = iter.next(); key = keyExtractor.apply(e); val = ret.computeIfAbsent(key, k -> new ArrayList<>()); val.add(valueExtractor.apply(e)); } return ret; } /** * Groups the elements in the given array by the key extracted by the specified {@code Function}. * The values in the resulting map are transformed by the specified collector. * * @param the type of elements in the array * @param the type of keys * @param the type of values in the resulting map * @param c the iterable to group * @param keyExtractor a function to extract the key for grouping * @param collector a collector that transforms the values * @return a map where the keys are extracted from the elements and the values are transformed by the collector. An empty map is returned if the input array is {@code null} or empty. */ @Beta public static Map groupBy(final Iterable c, final Function keyExtractor, final Collector collector) { return groupBy(c, keyExtractor, collector, Suppliers.ofMap()); } /** * Groups the elements in the given array by the key extracted by the specified {@code Function}. * The values in the resulting map are transformed by the specified collector. * * @param the type of elements in the array * @param the type of keys * @param the type of values in the resulting map * @param the type of returned map * @param c the iterable to group * @param keyExtractor a function to extract the key for grouping * @param collector a collector that transforms the values * @param mapSupplier a function to create the returned map * @return a map where the keys are extracted from the elements and the values are transformed by the collector. An empty map is returned if the input array is {@code null} or empty. */ @Beta public static > M groupBy(final Iterable c, final Function keyExtractor, final Collector collector, final Supplier mapSupplier) { final M ret = mapSupplier.get(); final Supplier downstreamSupplier = (Supplier) collector.supplier(); final BiConsumer downstreamAccumulator = (BiConsumer) collector.accumulator(); final Function downstreamFinisher = (Function) collector.finisher(); final Map intermediate = (Map) ret; if (c == null) { return ret; } K key = null; Object val = null; for (final T e : c) { key = keyExtractor.apply(e); if (((val = intermediate.get(key)) == null) && ((val = downstreamSupplier.get()) != null)) { intermediate.put(key, val); } downstreamAccumulator.accept(val, e); } updateIntermediateValue(intermediate, downstreamFinisher); return ret; } /** * Groups the elements in the given iterator by the key extracted by the specified {@code Function}. * The values in the resulting map are transformed by the specified collector. * * @param the type of elements in the iterator * @param the type of keys * @param the type of values in the resulting map * @param iter the iterator to group * @param keyExtractor a function to extract the key for grouping * @param collector a collector that transforms the values * @return a map where the keys are extracted from the elements and the values are transformed by the collector. An empty map is returned if the input iterator is {@code null} or empty. */ @Beta public static Map groupBy(final Iterator iter, final Function keyExtractor, final Collector collector) { return groupBy(iter, keyExtractor, collector, Suppliers.ofMap()); } /** * Groups the elements in the given iterator by the key extracted by the specified {@code Function}. * The values in the resulting map are transformed by the specified collector. * * @param the type of keys * @param the type of elements in the iterator * @param the type of values in the resulting map * @param the type of returned map * @param iter the iterator to group * @param keyExtractor a function to extract the key for grouping * @param collector a collector that transforms the values * @param mapSupplier a function to create the returned map * @return a map where the keys are extracted from the elements and the values are transformed by the collector. An empty map is returned if the input iterator is {@code null} or empty. */ @Beta public static > M groupBy(final Iterator iter, final Function keyExtractor, final Collector collector, final Supplier mapSupplier) { final M ret = mapSupplier.get(); final Supplier downstreamSupplier = (Supplier) collector.supplier(); final BiConsumer downstreamAccumulator = (BiConsumer) collector.accumulator(); final Function downstreamFinisher = (Function) collector.finisher(); final Map intermediate = (Map) ret; if (iter == null) { return ret; } T e = null; K key = null; Object val = null; while (iter.hasNext()) { e = iter.next(); key = keyExtractor.apply(e); if (((val = intermediate.get(key)) == null) && ((val = downstreamSupplier.get()) != null)) { intermediate.put(key, val); } downstreamAccumulator.accept(val, e); } updateIntermediateValue(intermediate, downstreamFinisher); return ret; } /** * Counts the elements in the given iterable by the key extracted by the specified {@code Function}. * The resulting map contains the keys and the count of elements associated with each key. * * @param the type of elements in the input iterable * @param the type of keys * @param c the input iterable to count * @param keyExtractor a function to extract the key for counting * @return a map where the keys are extracted from the elements and the values are the count of elements associated with each key. An empty map is returned if the input iterable is {@code null} or empty. */ @Beta public static Map countBy(final Iterable c, final Function keyExtractor) { return countBy(c, keyExtractor, Suppliers.ofMap()); } /** * Counts the elements in the given iterable by the key extracted by the specified {@code Function}. * The resulting map contains the keys and the count of elements associated with each key. * * @param the type of elements in the input iterable * @param the type of keys * @param the type of returned map * @param c the input iterable to count * @param keyExtractor a function to extract the key for counting * @param mapSupplier a function to create the returned map * @return a map where the keys are extracted from the elements and the values are the count of elements associated with each key. An empty map is returned if the input iterable is {@code null} or empty. */ @Beta public static > M countBy(final Iterable c, final Function keyExtractor, final Supplier mapSupplier) { final M ret = mapSupplier.get(); if (c == null) { return ret; } @SuppressWarnings("rawtypes") final Map intermediateMap = (Map) ret; K key = null; MutableInt val = null; for (final T e : c) { key = keyExtractor.apply(e); val = intermediateMap.get(key); if (val == null) { intermediateMap.put(key, MutableInt.of(1)); } else { val.increment(); } } updateIntermediateValue(intermediateMap, MutableInt::value); return ret; } /** * Counts the elements in the given iterator by the key extracted by the specified {@code Function}. * The resulting map contains the keys and the count of elements associated with each key. * * @param the type of elements in the input iterator * @param the type of keys * @param iter the input iterator to count * @param keyExtractor a function to extract the key for counting * @return a map where the keys are extracted from the elements and the values are the count of elements associated with each key. An empty map is returned if the input iterator is {@code null} or empty. */ @Beta public static Map countBy(final Iterator iter, final Function keyExtractor) { return countBy(iter, keyExtractor, Suppliers.ofMap()); } /** * Counts the elements in the given iterator by the key extracted by the specified {@code Function}. * The resulting map contains the keys and the count of elements associated with each key. * * @param the type of elements in the input iterator * @param the type of keys * @param the type of returned map * @param iter the input iterator to count * @param keyExtractor a function to extract the key for counting * @param mapSupplier a function to create the returned map * @return a map where the keys are extracted from the elements and the values are the count of elements associated with each key. An empty map is returned if the input iterator is {@code null} or empty. */ @Beta public static > M countBy(final Iterator iter, final Function keyExtractor, final Supplier mapSupplier) { final M ret = mapSupplier.get(); if (iter == null) { return ret; } @SuppressWarnings("rawtypes") final Map intermediateMap = (Map) ret; K key = null; MutableInt val = null; while (iter.hasNext()) { key = keyExtractor.apply(iter.next()); val = intermediateMap.get(key); if (val == null) { intermediateMap.put(key, MutableInt.of(1)); } else { val.increment(); } } updateIntermediateValue(intermediateMap, MutableInt::value); return ret; } static void updateIntermediateValue(final Map intermediate, final Function downstreamFinisher) { for (final Map.Entry entry : intermediate.entrySet()) { entry.setValue((V) downstreamFinisher.apply(entry.getValue())); } } /** * Returns an iterator over the elements in the specified array. * * @param the type of elements in the array * @param a the array to iterate over * @return an iterator over the elements in the specified array * @see ObjIterator#of(Object[]) * @see ObjIterator#of(Object[], int, int) */ @Beta public static Iterator iterate(final T[] a) { return ObjIterator.of(a); } /** * Returns an iterator over the elements within specified range in the given array. * * @param the type of elements in the array * @param a the array to iterate over * @param fromIndex the index of the first element (inclusive) to be iterated * @param toIndex the index of the last element (exclusive) to be iterated * @return an iterator over the elements within specified range in the specified array * @throws IndexOutOfBoundsException if the specified range is out of bounds * @see ObjIterator#of(Object[]) * @see ObjIterator#of(Object[], int, int) */ @Beta public static Iterator iterate(final T[] a, final int fromIndex, final int toIndex) throws IndexOutOfBoundsException { return ObjIterator.of(a, fromIndex, toIndex); } /** * Returns an iterator over the entries in the specified map. * * @param the type of keys maintained by the map * @param the type of mapped values * @param map the map whose entries are to be iterated * @return an iterator over the entries in the specified map */ @Beta public static Iterator> iterate(final Map map) { return map == null ? ObjIterator.empty() : map.entrySet().iterator(); } /** * Returns an iterator over the elements in the specified iterable. * * @param the type of elements in the iterable * @param c the iterable to iterate over * @return an iterator over the elements in the specified iterable * @see ObjIterator#of(Iterable) */ @Beta public static Iterator iterate(final Iterable c) { return c == null ? ObjIterator.empty() : (Iterator) c.iterator(); } /** * Returns a list of iterators for each iterable in the specified collection of iterables. * * @param the type of elements in the iterables * @param iterables the collection of iterables to iterate over * @return a list of iterators for each iterable in the specified collection */ @Beta public static List> iterateAll(final Collection> iterables) { final List> iterators = new ArrayList<>(size(iterables)); if (iterables != null) { for (final Iterable iterable : iterables) { iterators.add(iterate(iterable)); } } return iterators; } /** * Checks if the two specified arrays have no elements in common. * * @param a the first array to be checked * @param b the second array to be checked * @return {@code true} if the two arrays have no elements in common or either of specified arrays is {@code null} or empty, {@code false} otherwise. * @see Collections#disjoint(Collection, Collection) */ public static boolean disjoint(final Object[] a, final Object[] b) { if (isEmpty(a) || isEmpty(b)) { return true; } return a.length >= b.length ? disjoint(Arrays.asList(a), asSet(b)) : disjoint(asSet(a), Arrays.asList(b)); } /** * Checks if the two specified collections have no elements in common. * * @param c1 the first collection to be checked * @param c2 the second collection to be checked * @return {@code true} if the two collections have no elements in common or either of specified collections is {@code null} or empty, {@code false} otherwise. * @see Collections#disjoint(Collection, Collection) */ public static boolean disjoint(final Collection c1, final Collection c2) { if (isEmpty(c1) || isEmpty(c2)) { return true; } if (c1 instanceof Set || (!(c2 instanceof Set) && c1.size() > c2.size())) { for (final Object e : c2) { if (c1.contains(e)) { return false; } } } else { for (final Object e : c1) { if (c2.contains(e)) { return false; } } } return true; } /** * Converts the given object to its JSON string representation. * * @param obj the object to be converted to JSON * @return a JSON string representation in the given object */ public static String toJson(final Object obj) { return Utils.jsonParser.serialize(obj, Utils.jsc); } /** * Converts the given object to its JSON string representation with an option for pretty formatting. * * @param obj the object to be converted to JSON * @param prettyFormat a boolean flag that indicates whether the output JSON should be formatted with indents and line breaks for easier reading or not. * @return a JSON string representation in the given object. */ public static String toJson(final Object obj, final boolean prettyFormat) { return Utils.jsonParser.serialize(obj, prettyFormat ? Utils.jscPrettyFormat : Utils.jsc); } /** * Converts the given object to its JSON string representation with the specified {@code JSONSerializationConfig}. * * @param obj the object to be converted to JSON * @param config the JSON serialization configuration * @return a JSON string representation in the given object */ public static String toJson(final Object obj, final JSONSerializationConfig config) { return Utils.jsonParser.serialize(obj, config); } /** * Converts the given object to its JSON string representation and writes it to the specified file. * * @param obj the object to be converted to JSON * @param output the file to which the JSON string representation of the object will be written */ public static void toJson(final Object obj, final File output) { Utils.jsonParser.serialize(obj, output); } /** * Converts the given object to its JSON string representation with an option for pretty formatting and writes it to the specified file. * * @param obj the object to be converted to JSON * @param config the JSON serialization configuration * @param output the file to which the JSON string representation of the object will be written */ public static void toJson(final Object obj, final JSONSerializationConfig config, final File output) { Utils.jsonParser.serialize(obj, config, output); } /** * Converts the given object to its JSON string representation and writes it to the specified output stream. * * @param obj the object to be converted to JSON * @param output the output stream to which the JSON string representation of the object will be written */ public static void toJson(final Object obj, final OutputStream output) { Utils.jsonParser.serialize(obj, output); } /** * Converts the given object to its JSON string representation with an option for pretty formatting and writes it to the specified output stream. * * @param obj the object to be converted to JSON * @param config the JSON serialization configuration * @param output the output stream to which the JSON string representation of the object will be written */ public static void toJson(final Object obj, final JSONSerializationConfig config, final OutputStream output) { Utils.jsonParser.serialize(obj, config, output); } /** * Converts the given object to its JSON string representation and writes it to the specified writer. * * @param obj the object to be converted to JSON * @param output the writer to which the JSON string representation of the object will be written */ public static void toJson(final Object obj, final Writer output) { Utils.jsonParser.serialize(obj, output); } /** * Converts the given object to its JSON string representation with an option for pretty formatting and writes it to the specified writer. * * @param obj the object to be converted to JSON * @param config the JSON serialization configuration * @param output the writer to which the JSON string representation of the object will be written */ public static void toJson(final Object obj, final JSONSerializationConfig config, final Writer output) { Utils.jsonParser.serialize(obj, config, output); } /** * Deserializes the given JSON string into an object of the specified target type. * * @param the type of the object to be returned * @param json the JSON string to be deserialized * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final String json, final Class targetType) { return Utils.jsonParser.deserialize(json, targetType); } /** * Deserializes the given JSON string into an object of the specified target type. * * @param the type of the object to be returned * @param json the JSON string to be deserialized * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final String json, final Type targetType) { return fromJson(json, null, targetType); } /** * Deserializes the given JSON string into an object of the specified target type. * If the deserialized object is {@code null}, returns the provided default value. * * @param the type of the object to be returned * @param json the JSON string to be deserialized * @param defaultIfNull the default value to return if the deserialized object is null * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string, or defaultIfNull if the deserialized object is null * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final String json, final T defaultIfNull, final Class targetType) { final T ret = fromJson(json, targetType); return ret == null ? defaultIfNull : ret; } /** * Deserializes the given JSON string into an object of the specified target type. * If the deserialized object is {@code null}, returns the provided default value. * * @param the type of the object to be returned * @param json the JSON string to be deserialized * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @param targetType can be the {@code Type} of {@code Bean/Array/Collection/Map}. * @return an object of type T deserialized from the JSON string, or defaultIfNull if the deserialized object is null * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final String json, final T defaultIfNull, final Type targetType) { final T ret = fromJson(json, targetType); return ret == null ? defaultIfNull : ret; } /** * Deserializes the given JSON string into an object of the specified target type with the specified {@code JSONDeserializationConfig}. * * @param the type of the object to be returned * @param json the JSON string to be deserialized * @param config the JSON deserialization configuration * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final String json, final JSONDeserializationConfig config, final Class targetType) { return Utils.jsonParser.deserialize(json, config, targetType); } /** * Deserializes the given JSON string into an object of the specified target type with the specified {@code JSONDeserializationConfig}. * * @param the type of the object to be returned * @param json the JSON string to be deserialized * @param config the JSON deserialization configuration * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final String json, final JSONDeserializationConfig config, final Type targetType) { return Utils.jsonParser.deserialize(json, setConfig(targetType, config, true), targetType.clazz()); } /** * Deserializes the given JSON string from the specified file into an object of the specified target type. * * @param the type of the object to be returned * @param json the file where the given JSON string is read to be deserialized * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final File json, final Class targetType) { return Utils.jsonParser.deserialize(json, targetType); } /** * Deserializes the given JSON string from the specified file into an object of the specified target type. * * @param the type of the object to be returned * @param json the file where the given JSON string is read to be deserialized * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final File json, final Type targetType) { return fromJson(json, null, targetType); } /** * Deserializes the given JSON string from the specified file into an object of the specified target type with the specified {@code JSONDeserializationConfig}. * * @param the type of the object to be returned * @param json the file where the given JSON string is read to be deserialized * @param config the JSON deserialization configuration * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final File json, final JSONDeserializationConfig config, final Class targetType) { return Utils.jsonParser.deserialize(json, config, targetType); } /** * Deserializes the given JSON string from the specified file into an object of the specified target type with the specified {@code JSONDeserializationConfig}. * * @param the type of the object to be returned * @param json the file where the given JSON string is read to be deserialized * @param config the JSON deserialization configuration * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final File json, final JSONDeserializationConfig config, final Type targetType) { return Utils.jsonParser.deserialize(json, setConfig(targetType, config, true), targetType.clazz()); } /** * Deserializes the given JSON string from the specified input stream into an object of the specified target type. * * @param the type of the object to be returned * @param json the input stream where the given JSON string is read to be deserialized * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final InputStream json, final Class targetType) { return Utils.jsonParser.deserialize(json, targetType); } /** * Deserializes the given JSON string from the specified input stream into an object of the specified target type. * * @param the type of the object to be returned * @param json the input stream where the given JSON string is read to be deserialized * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final InputStream json, final Type targetType) { return fromJson(json, null, targetType); } /** * Deserializes the given JSON string from the specified input stream into an object of the specified target type with the specified {@code JSONDeserializationConfig}. * * @param the type of the object to be returned * @param json the input stream where the given JSON string is read to be deserialized * @param config the JSON deserialization configuration * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final InputStream json, final JSONDeserializationConfig config, final Class targetType) { return Utils.jsonParser.deserialize(json, config, targetType); } /** * Deserializes the given JSON string from the specified input stream into an object of the specified target type with the specified {@code JSONDeserializationConfig}. * * @param the type of the object to be returned * @param json the input stream where the given JSON string is read to be deserialized * @param config the JSON deserialization configuration * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final InputStream json, final JSONDeserializationConfig config, final Type targetType) { return Utils.jsonParser.deserialize(json, setConfig(targetType, config, true), targetType.clazz()); } /** * Deserializes the given JSON string from the specified reader into an object of the specified target type. * * @param the type of the object to be returned * @param json the reader where the given JSON string is read to be deserialized * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final Reader json, final Class targetType) { return Utils.jsonParser.deserialize(json, targetType); } /** * Deserializes the given JSON string from the specified reader into an object of the specified target type. * * @param the type of the object to be returned * @param json the reader where the given JSON string is read to be deserialized * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final Reader json, final Type targetType) { return fromJson(json, null, targetType); } /** * Deserializes the given JSON string from the specified reader into an object of the specified target type with the specified {@code JSONDeserializationConfig}. * * @param the type of the object to be returned * @param json the reader where the given JSON string is read to be deserialized * @param config the JSON deserialization configuration * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final Reader json, final JSONDeserializationConfig config, final Class targetType) { return Utils.jsonParser.deserialize(json, config, targetType); } /** * Deserializes the given JSON string from the specified reader into an object of the specified target type with the specified {@code JSONDeserializationConfig}. * * @param the type of the object to be returned * @param json the reader where the given JSON string is read to be deserialized * @param config the JSON deserialization configuration * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final Reader json, final JSONDeserializationConfig config, final Type targetType) { return Utils.jsonParser.deserialize(json, setConfig(targetType, config, true), targetType.clazz()); } /** * Deserializes the given JSON sub-string in the specified range into an object of the specified target type. * * @param the type of the object to be returned * @param json the JSON string to be deserialized * @param fromIndex the index of the first character (inclusive) to be deserialized * @param toIndex the index of the last character (exclusive) to be deserialized * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string * @throws IllegalArgumentException if the specified target type is {@code null}. * @throws IndexOutOfBoundsException if the specified range is out of bounds * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final String json, final int fromIndex, final int toIndex, final Class targetType) throws IndexOutOfBoundsException { return Utils.jsonParser.deserialize(json, fromIndex, toIndex, targetType); } /** * Deserializes the given JSON sub-string in the specified range into an object of the specified target type. * * @param the type of the object to be returned * @param json the JSON string to be deserialized * @param fromIndex the index of the first character (inclusive) to be deserialized * @param toIndex the index of the last character (exclusive) to be deserialized * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string * @throws IllegalArgumentException if the specified target type is {@code null}. * @throws IndexOutOfBoundsException if the specified range is out of bounds * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final String json, final int fromIndex, final int toIndex, final Type targetType) throws IndexOutOfBoundsException { return fromJson(json, fromIndex, toIndex, null, targetType); } /** * Deserializes the given JSON sub-string in the specified range into an object of the specified target type with the specified {@code JSONDeserializationConfig}. * * @param the type of the object to be returned * @param json the JSON string to be deserialized * @param config the JSON deserialization configuration * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string * @throws IllegalArgumentException if the specified target type is {@code null}. * @throws IndexOutOfBoundsException if the specified range is out of bounds * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final String json, final int fromIndex, final int toIndex, final JSONDeserializationConfig config, final Class targetType) { return Utils.jsonParser.deserialize(json, fromIndex, toIndex, config, targetType); } /** * Deserializes the given JSON sub-string in the specified range into an object of the specified target type with the specified {@code JSONDeserializationConfig}. * * @param the type of the object to be returned * @param json the JSON string to be deserialized * @param fromIndex the index of the first character (inclusive) to be deserialized * @param toIndex the index of the last character (exclusive) to be deserialized * @param config the JSON deserialization configuration * @param targetType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return an object of type T deserialized from the JSON string * @throws IndexOutOfBoundsException if the specified range is out of bounds * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromJson(final String json, final int fromIndex, final int toIndex, final JSONDeserializationConfig config, final Type targetType) throws IndexOutOfBoundsException { return Utils.jsonParser.deserialize(json, fromIndex, toIndex, setConfig(targetType, config, true), targetType.clazz()); } /** * Creates a stream of elements deserialized from the given JSON array string with the specified target type. * * @param the type of the elements in the JSON array * @param jsonArray the JSON array string to be streamed * @param elementType the type the given JSON array element will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return a stream of elements deserialized from the given JSON array * @throws IllegalArgumentException if the specified element type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static Stream streamJson(final String jsonArray, final Class elementType) { return Utils.jsonParser.stream(jsonArray, elementType); } /** * Creates a stream of elements deserialized from the given JSON array string with the specified target type. * * @param the type of the elements in the JSON array * @param jsonArray the JSON array string to be streamed * @param elementType the type the given JSON array element will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return a stream of elements deserialized from the given JSON array * @throws IllegalArgumentException if the specified element type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static Stream streamJson(final String jsonArray, final Type elementType) { return streamJson(jsonArray, null, elementType); } /** * Creates a stream of elements deserialized from the given JSON array string with the specified target type and {@code JSONDeserializationConfig}. * * @param the type of the elements in the JSON array * @param jsonArray the JSON array string to be streamed * @param config the JSON deserialization configuration * @param elementType the type the given JSON array element will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return a stream of elements deserialized from the given JSON array * @throws IllegalArgumentException if the specified element type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static Stream streamJson(final String jsonArray, final JSONDeserializationConfig config, final Class elementType) { return Utils.jsonParser.stream(jsonArray, config, elementType); } /** * Creates a stream of elements deserialized from the given JSON array string with the specified target type and {@code JSONDeserializationConfig}. * * @param the type of the elements in the JSON array * @param jsonArray the JSON array string to be streamed * @param config the JSON deserialization configuration * @param elementType the type the given JSON array element will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return a stream of elements deserialized from the given JSON array * @throws IllegalArgumentException if the specified element type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static Stream streamJson(final String jsonArray, final JSONDeserializationConfig config, final Type elementType) { return Utils.jsonParser.stream(jsonArray, setElementType(config, elementType), elementType.clazz()); } /** * Creates a stream of elements deserialized from the given JSON array in the specified file with the specified target type. * * @param the type of the elements in the JSON array * @param jsonArray the JSON array file to be streamed * @param elementType the type the given JSON array element will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return a stream of elements deserialized from the given JSON array * @throws IllegalArgumentException if the specified element type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static Stream streamJson(final File jsonArray, final Class elementType) { return Utils.jsonParser.stream(jsonArray, elementType); } /** * Creates a stream of elements deserialized from the given JSON array in the specified file with the specified target type. * * @param the type of the elements in the JSON array * @param jsonArray the JSON array file to be streamed * @param elementType the type the given JSON array element will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return a stream of elements deserialized from the given JSON array * @throws IllegalArgumentException if the specified element type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static Stream streamJson(final File jsonArray, final Type elementType) { return streamJson(jsonArray, null, elementType); } /** * Creates a stream of elements deserialized from the given JSON array in the specified file with the specified target type and {@code JSONDeserializationConfig}. * * @param the type of the elements in the JSON array * @param jsonArray the JSON array file to be streamed * @param config the JSON deserialization configuration * @param elementType the type the given JSON array element will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return a stream of elements deserialized from the given JSON array * @throws IllegalArgumentException if the specified element type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static Stream streamJson(final File jsonArray, final JSONDeserializationConfig config, final Class elementType) { return Utils.jsonParser.stream(jsonArray, config, elementType); } /** * Creates a stream of elements deserialized from the given JSON array in the specified file with the specified target type and {@code JSONDeserializationConfig}. * * @param the type of the elements in the JSON array * @param jsonArray the JSON array file to be streamed * @param config the JSON deserialization configuration * @param elementType the type the given JSON array element will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return a stream of elements deserialized from the given JSON array * @throws IllegalArgumentException if the specified element type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static Stream streamJson(final File jsonArray, final JSONDeserializationConfig config, final Type elementType) { return Utils.jsonParser.stream(jsonArray, setElementType(config, elementType), elementType.clazz()); } /** * Creates a stream of elements deserialized from the given JSON array in the specified input stream with the specified target type. * * @param the type of the elements in the JSON array * @param jsonArray the input stream where the given JSON array is read to be streamed * @param elementType the type the given JSON array element will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return a stream of elements deserialized from the given JSON array * @throws IllegalArgumentException if the specified element type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static Stream streamJson(final InputStream jsonArray, final Class elementType) { return streamJson(jsonArray, false, elementType); } /** * Creates a stream of elements deserialized from the given JSON array in the specified input stream with the specified target type. * * @param the type of the elements in the JSON array * @param jsonArray the input stream where the given JSON array is read to be streamed * @param elementType the type the given JSON array element will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return a stream of elements deserialized from the given JSON array * @throws IllegalArgumentException if the specified element type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static Stream streamJson(final InputStream jsonArray, final Type elementType) { return streamJson(jsonArray, false, elementType); } /** * Creates a stream of elements deserialized from the given JSON array in the specified input stream with the specified target type and {@code JSONDeserializationConfig}. * * @param the type of the elements in the JSON array * @param jsonArray the input stream where the given JSON array is read to be streamed * @param closeInputStreamWhenStreamIsClosed the flag indicating whether to close the input stream when the stream is closed * @param elementType the type the given JSON array element will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return a stream of elements deserialized from the given JSON array * @throws IllegalArgumentException if the specified element type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static Stream streamJson(final InputStream jsonArray, final boolean closeInputStreamWhenStreamIsClosed, final Class elementType) { return Utils.jsonParser.stream(jsonArray, closeInputStreamWhenStreamIsClosed, elementType); } /** * Creates a stream of elements deserialized from the given JSON array in the specified input stream with the specified target type and {@code JSONDeserializationConfig}. * * @param the type of the elements in the JSON array * @param jsonArray the input stream where the given JSON array is read to be streamed * @param closeInputStreamWhenStreamIsClosed the flag indicating whether to close the input stream when the stream is closed * @param elementType the type the given JSON array element will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return a stream of elements deserialized from the given JSON array * @throws IllegalArgumentException if the specified element type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static Stream streamJson(final InputStream jsonArray, final boolean closeInputStreamWhenStreamIsClosed, final Type elementType) { return streamJson(jsonArray, null, closeInputStreamWhenStreamIsClosed, elementType); } /** * Creates a stream of elements deserialized from the given JSON array in the specified input stream with the specified target type and {@code JSONDeserializationConfig}. * * @param the type of the elements in the JSON array * @param jsonArray the input stream where the given JSON array is read to be streamed * @param config the JSON deserialization configuration * @param closeInputStreamWhenStreamIsClosed the flag indicating whether to close the input stream when the stream is closed * @param elementType the type the given JSON array element will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return a stream of elements deserialized from the given JSON array * @throws IllegalArgumentException if the specified element type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static Stream streamJson(final InputStream jsonArray, final JSONDeserializationConfig config, final boolean closeInputStreamWhenStreamIsClosed, final Class elementType) { return Utils.jsonParser.stream(jsonArray, config, closeInputStreamWhenStreamIsClosed, elementType); } /** * Creates a stream of elements deserialized from the given JSON array in the specified input stream with the specified target type and {@code JSONDeserializationConfig}. * * @param the type of the elements in the JSON array * @param jsonArray the input stream where the given JSON array is read to be streamed * @param config the JSON deserialization configuration * @param closeInputStreamWhenStreamIsClosed the flag indicating whether to close the input stream when the stream is closed * @param elementType the type the given JSON array element will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return a stream of elements deserialized from the given JSON array * @throws IllegalArgumentException if the specified element type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static Stream streamJson(final InputStream jsonArray, final JSONDeserializationConfig config, final boolean closeInputStreamWhenStreamIsClosed, final Type elementType) { return Utils.jsonParser.stream(jsonArray, setElementType(config, elementType), closeInputStreamWhenStreamIsClosed, elementType.clazz()); } /** * Creates a stream of elements deserialized from the given JSON array in the specified reader with the specified target type. * * @param the type of the elements in the JSON array * @param jsonArray the reader where the given JSON array is read to be streamed * @param elementType the type the given JSON array element will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return a stream of elements deserialized from the given JSON array * @throws IllegalArgumentException if the specified element type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static Stream streamJson(final Reader jsonArray, final Class elementType) { return streamJson(jsonArray, false, elementType); } /** * Creates a stream of elements deserialized from the given JSON array in the specified reader with the specified target type. * * @param the type of the elements in the JSON array * @param jsonArray the reader where the given JSON array is read to be streamed * @param elementType the type the given JSON array element will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return a stream of elements deserialized from the given JSON array * @throws IllegalArgumentException if the specified element type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static Stream streamJson(final Reader jsonArray, final Type elementType) { return streamJson(jsonArray, false, elementType); } /** * Creates a stream of elements deserialized from the given JSON array in the specified reader with the specified target type and {@code JSONDeserializationConfig}. * * @param the type of the elements in the JSON array * @param jsonArray the reader where the given JSON array is read to be streamed * @param closeReaderWhenStreamIsClosed the flag indicating whether to close the reader when the stream is closed * @param elementType the type the given JSON array element will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return a stream of elements deserialized from the given JSON array * @throws IllegalArgumentException if the specified element type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static Stream streamJson(final Reader jsonArray, final boolean closeReaderWhenStreamIsClosed, final Class elementType) { return Utils.jsonParser.stream(jsonArray, closeReaderWhenStreamIsClosed, elementType); } /** * Creates a stream of elements deserialized from the given JSON array in the specified reader with the specified target type and {@code JSONDeserializationConfig}. * * @param the type of the elements in the JSON array * @param jsonArray the reader where the given JSON array is read to be streamed * @param closeReaderWhenStreamIsClosed the flag indicating whether to close the reader when the stream is closed * @param elementType the type the given JSON array element will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return a stream of elements deserialized from the given JSON array * @throws IllegalArgumentException if the specified element type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static Stream streamJson(final Reader jsonArray, final boolean closeReaderWhenStreamIsClosed, final Type elementType) { return streamJson(jsonArray, null, closeReaderWhenStreamIsClosed, elementType); } /** * Creates a stream of elements deserialized from the given JSON array in the specified reader with the specified target type and {@code JSONDeserializationConfig}. * * @param the type of the elements in the JSON array * @param jsonArray the reader where the given JSON array is read to be streamed * @param config the JSON deserialization configuration * @param closeReaderWhenStreamIsClosed the flag indicating whether to close the reader when the stream is closed * @param elementType the type the given JSON array element will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return a stream of elements deserialized from the given JSON array * @throws IllegalArgumentException if the specified element type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static Stream streamJson(final Reader jsonArray, final JSONDeserializationConfig config, final boolean closeReaderWhenStreamIsClosed, final Class elementType) { return Utils.jsonParser.stream(jsonArray, config, closeReaderWhenStreamIsClosed, elementType); } /** * Creates a stream of elements deserialized from the given JSON array in the specified reader with the specified target type and {@code JSONDeserializationConfig}. * * @param the type of the elements in the JSON array * @param jsonArray the reader where the given JSON array is read to be streamed * @param config the JSON deserialization configuration * @param closeReaderWhenStreamIsClosed the flag indicating whether to close the reader when the stream is closed * @param elementType the type the given JSON array element will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return a stream of elements deserialized from the given JSON array * @throws IllegalArgumentException if the specified element type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static Stream streamJson(final Reader jsonArray, final JSONDeserializationConfig config, final boolean closeReaderWhenStreamIsClosed, final Type elementType) { return Utils.jsonParser.stream(jsonArray, setElementType(config, elementType), closeReaderWhenStreamIsClosed, elementType.clazz()); } private static JSONDeserializationConfig setElementType(final JSONDeserializationConfig config, final Type elementType) { final JSONDeserializationConfig configToReturn = config == null ? JDC.create() : config.copy(); configToReturn.setElementType(elementType); return configToReturn; } private static > C setConfig(final Type targetType, final C config, final boolean isJSON) { C configToReturn = config; if (targetType.isCollection() || targetType.isArray()) { if (config == null || config.getElementType() == null) { configToReturn = config == null ? (C) (isJSON ? JDC.create() : XDC.create()) : config.copy(); configToReturn.setElementType(targetType.getParameterTypes()[0]); } } else if (targetType.isMap() && (config == null || config.getMapKeyType() == null || config.getMapValueType() == null)) { configToReturn = config == null ? (C) (isJSON ? JDC.create() : XDC.create()) : config.copy(); if (configToReturn.getMapKeyType() == null) { configToReturn.setMapKeyType(targetType.getParameterTypes()[0]); } if (configToReturn.getMapValueType() == null) { configToReturn.setMapValueType(targetType.getParameterTypes()[1]); } } return configToReturn; } /** * Formats the given JSON string to its pretty-printed JSON format with indents and line breaks for easier reading. * * @param json the JSON string to be formatted * @return the formatted JSON string */ public static String formatJson(final String json) { return formatJson(json, Utils.jscPrettyFormat, Object.class); } /** * Formats the given JSON string to its pretty-printed JSON format with indents and line breaks for easier reading. * * @param json the JSON string to be formatted * @param transferType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return the formatted JSON string */ public static String formatJson(final String json, final Class transferType) { return toJson(fromJson(json, transferType), Utils.jscPrettyFormat); } /** * Formats the given JSON string to its pretty-printed JSON format with indents and line breaks for easier reading. * * @param json the JSON string to be formatted * @param transferType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return the formatted JSON string */ public static String formatJson(final String json, final Type transferType) { return toJson(fromJson(json, transferType), Utils.jscPrettyFormat); } /** * Formats the given JSON string to its pretty-printed JSON format with indents and line breaks for easier reading. * * @param json the JSON string to be formatted * @param config the JSON serialization configuration * @return the formatted JSON string */ public static String formatJson(final String json, final JSONSerializationConfig config) { return formatJson(json, config, Object.class); } /** * Formats the given JSON string to its pretty-printed JSON format with indents and line breaks for easier reading. * * @param json the JSON string to be formatted * @param config the JSON serialization configuration * @param transferType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return the formatted JSON string */ public static String formatJson(final String json, final JSONSerializationConfig config, final Class transferType) { final JSONSerializationConfig configToUse = config == null ? Utils.jscPrettyFormat : (!config.prettyFormat() ? config.copy().prettyFormat(true) : config); return toJson(fromJson(json, transferType), configToUse); } /** * Formats the given JSON string to its pretty-printed JSON format with indents and line breaks for easier reading. * * @param json the JSON string to be formatted * @param config the JSON serialization configuration * @param transferType the type the given JSON string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet} or serializable single value type, e.g. {@code String, Integer, Date} * @return the formatted JSON string */ public static String formatJson(final String json, final JSONSerializationConfig config, final Type transferType) { final JSONSerializationConfig configToUse = config == null ? Utils.jscPrettyFormat : (!config.prettyFormat() ? config.copy().prettyFormat(true) : config); return toJson(fromJson(json, transferType), configToUse); } /** * Converts the given object into an XML string representation. * * @param obj the object to be converted into an XML string. * @return an XML string representation in the given object. */ public static String toXml(final Object obj) { return Utils.xmlParser.serialize(obj); } /** * Converts the given object to its XML string representation with an option for pretty formatting. * * @param obj the object to be converted to XML * @param prettyFormat a boolean flag that indicates whether the output XML should be formatted with indents and line breaks for easier reading or not. * @return a XML string representation in the given object. */ public static String toXml(final Object obj, final boolean prettyFormat) { return Utils.xmlParser.serialize(obj, prettyFormat ? Utils.xscPrettyFormat : Utils.xsc); } /** * Converts the given object to its XML string representation with the specified {@code XMLSerializationConfig}. * * @param obj the object to be converted to XML * @param config the XML serialization configuration * @return a XML string representation in the given object. */ public static String toXml(final Object obj, final XMLSerializationConfig config) { return Utils.xmlParser.serialize(obj, config); } /** * Converts the given object to its XML string representation and writes it to the specified file. * * @param obj the object to be converted to XML * @param output the file to which the XML string representation of the object will be written */ public static void toXml(final Object obj, final File output) { Utils.xmlParser.serialize(obj, output); } /** * Converts the given object to its XML string representation with the specified {@code XMLSerializationConfig} and writes it to the specified file. * * @param obj the object to be converted to XML * @param config the XML serialization configuration * @param output the file to which the XML string representation of the object will be written */ public static void toXml(final Object obj, final XMLSerializationConfig config, final File output) { Utils.xmlParser.serialize(obj, config, output); } /** * Converts the given object to its XML string representation and writes it to the specified output stream. * * @param obj the object to be converted to XML * @param output the output stream to which the XML string representation of the object will be written */ public static void toXml(final Object obj, final OutputStream output) { Utils.xmlParser.serialize(obj, output); } /** * Converts the given object to its XML string representation with the specified {@code XMLSerializationConfig} and writes it to the specified output stream. * * @param obj the object to be converted to XML * @param config the XML serialization configuration * @param output the output stream to which the XML string representation of the object will be written */ public static void toXml(final Object obj, final XMLSerializationConfig config, final OutputStream output) { Utils.xmlParser.serialize(obj, config, output); } /** * Converts the given object to its XML string representation and writes it to the specified writer. * * @param obj the object to be converted to XML * @param output the writer to which the XML string representation of the object will be written */ public static void toXml(final Object obj, final Writer output) { Utils.xmlParser.serialize(obj, output); } /** * Converts the given object to its XML string representation with the specified {@code XMLSerializationConfig} and writes it to the specified writer. * * @param obj the object to be converted to XML * @param config the XML serialization configuration * @param output the writer to which the XML string representation of the object will be written */ public static void toXml(final Object obj, final XMLSerializationConfig config, final Writer output) { Utils.xmlParser.serialize(obj, config, output); } /** * Deserializes the given XML string into an object of the specified target type. * * @param the type of the object to be returned * @param xml the XML string to be deserialized * @param targetType the type the given XML string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet}. * @return an object of type T deserialized from the XML string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromXml(final String xml, final Class targetType) { return Utils.xmlParser.deserialize(xml, targetType); } /** * Deserializes the given XML string into an object of the specified target type. * * @param the type of the object to be returned * @param xml the XML string to be deserialized * @param targetType the type the given XML string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map}. * @return an object of type T deserialized from the XML string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromXml(final String xml, final Type targetType) { return fromJson(xml, null, targetType); } /** * Deserializes the given XML string into an object of the specified target type with the specified {@code XMLDeserializationConfig}. * * @param the type of the object to be returned * @param xml the XML string to be deserialized * @param config the XML deserialization configuration * @param targetType the type the given XML string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet}. * @return an object of type T deserialized from the XML string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromXml(final String xml, final XMLDeserializationConfig config, final Class targetType) { return Utils.xmlParser.deserialize(xml, config, targetType); } /** * Deserializes the given XML string into an object of the specified target type with the specified {@code XMLDeserializationConfig}. * * @param the type of the object to be returned * @param xml the XML string to be deserialized * @param config the XML deserialization configuration * @param targetType the type the given XML string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map}. * @return an object of type T deserialized from the XML string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromXml(final String xml, final XMLDeserializationConfig config, final Type targetType) { return Utils.xmlParser.deserialize(xml, setConfig(targetType, config, false), targetType.clazz()); } /** * Deserializes the given XML string from the specified file into an object of the specified target type. * * @param the type of the object to be returned * @param xml the file where the given XML string is read to be deserialized * @param targetType the type the given XML string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet}. * @return an object of type T deserialized from the XML string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromXml(final File xml, final Class targetType) { return Utils.xmlParser.deserialize(xml, targetType); } /** * Deserializes the given XML string from the specified file into an object of the specified target type. * * @param the type of the object to be returned * @param xml the file where the given XML string is read to be deserialized * @param targetType the type the given XML string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map}. * @return an object of type T deserialized from the XML string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromXml(final File xml, final Type targetType) { return fromJson(xml, null, targetType); } /** * Deserializes the given XML string from the specified file into an object of the specified target type with the specified {@code XMLDeserializationConfig}. * * @param the type of the object to be returned * @param xml the file where the given XML string is read to be deserialized * @param config the XML deserialization configuration * @param targetType the type the given XML string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet}. * @return an object of type T deserialized from the XML string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromXml(final File xml, final XMLDeserializationConfig config, final Class targetType) { return Utils.xmlParser.deserialize(xml, config, targetType); } /** * Deserializes the given XML string from the specified file into an object of the specified target type with the specified {@code XMLDeserializationConfig}. * * @param the type of the object to be returned * @param xml the file where the given XML string is read to be deserialized * @param config the XML deserialization configuration * @param targetType the type the given XML string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map}. * @return an object of type T deserialized from the XML string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromXml(final File xml, final XMLDeserializationConfig config, final Type targetType) { return Utils.xmlParser.deserialize(xml, setConfig(targetType, config, false), targetType.clazz()); } /** * Deserializes the given XML string from the specified input stream into an object of the specified target type. * * @param the type of the object to be returned * @param xml the input stream where the given XML string is read to be deserialized * @param targetType the type the given XML string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet}. * @return an object of type T deserialized from the XML string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromXml(final InputStream xml, final Class targetType) { return Utils.xmlParser.deserialize(xml, targetType); } /** * Deserializes the given XML string from the specified input stream into an object of the specified target type. * * @param the type of the object to be returned * @param xml the input stream where the given XML string is read to be deserialized * @param targetType the type the given XML string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map}. * @return an object of type T deserialized from the XML string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromXml(final InputStream xml, final Type targetType) { return fromJson(xml, null, targetType); } /** * Deserializes the given XML string from the specified input stream into an object of the specified target type with the specified {@code XMLDeserializationConfig}. * * @param the type of the object to be returned * @param xml the input stream where the given XML string is read to be deserialized * @param config the XML deserialization configuration * @param targetType the type the given XML string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet}. * @return an object of type T deserialized from the XML string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromXml(final InputStream xml, final XMLDeserializationConfig config, final Class targetType) { return Utils.xmlParser.deserialize(xml, config, targetType); } /** * Deserializes the given XML string from the specified input stream into an object of the specified target type with the specified {@code XMLDeserializationConfig}. * * @param the type of the object to be returned * @param xml the input stream where the given XML string is read to be deserialized * @param config the XML deserialization configuration * @param targetType the type the given XML string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map}. * @return an object of type T deserialized from the XML string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromXml(final InputStream xml, final XMLDeserializationConfig config, final Type targetType) { return Utils.xmlParser.deserialize(xml, setConfig(targetType, config, false), targetType.clazz()); } /** * Deserializes the given XML string from the specified reader into an object of the specified target type. * * @param the type of the object to be returned * @param xml the reader where the given XML string is read to be deserialized * @param targetType the type the given XML string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet}. * @return an object of type T deserialized from the XML string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromXml(final Reader xml, final Class targetType) { return Utils.xmlParser.deserialize(xml, targetType); } /** * Deserializes the given XML string from the specified reader into an object of the specified target type. * * @param the type of the object to be returned * @param xml the reader where the given XML string is read to be deserialized * @param targetType the type the given XML string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map}. * @return an object of type T deserialized from the XML string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromXml(final Reader xml, final Type targetType) { return fromJson(xml, null, targetType); } /** * Deserializes the given XML string from the specified reader into an object of the specified target type with the specified {@code XMLDeserializationConfig}. * * @param the type of the object to be returned * @param xml the reader where the given XML string is read to be deserialized * @param config the XML deserialization configuration * @param targetType the type the given XML string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet}. * @return an object of type T deserialized from the XML string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.type.Type * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromXml(final Reader xml, final XMLDeserializationConfig config, final Class targetType) { return Utils.xmlParser.deserialize(xml, config, targetType); } /** * Deserializes the given XML string from the specified reader into an object of the specified target type with the specified {@code XMLDeserializationConfig}. * * @param the type of the object to be returned * @param xml the reader where the given XML string is read to be deserialized * @param config the XML deserialization configuration * @param targetType the type the given XML string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map}. * @return an object of type T deserialized from the XML string * @throws IllegalArgumentException if the specified target type is {@code null}. * @see com.landawn.abacus.util.TypeReference * @see com.landawn.abacus.util.TypeReference.TypeToken */ public static T fromXml(final Reader xml, final XMLDeserializationConfig config, final Type targetType) { return Utils.xmlParser.deserialize(xml, setConfig(targetType, config, false), targetType.clazz()); } /** * Formats the given XML string to its pretty-printed XML format with indents and line breaks for easier reading. * * @param xml the XML string to be formatted * @return the formatted XML string */ public static String formatXml(final String xml) { return formatXml(xml, MapEntity.class); } /** * Formats the given XML string to its pretty-printed XML format with indents and line breaks for easier reading. * * @param xml the XML string to be formatted * @param transferType the type the given XML string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet}. * @return the formatted XML string */ public static String formatXml(final String xml, final Class transferType) { return toXml(fromXml(xml, transferType), Utils.xscPrettyFormat); } /** * Formats the given XML string to its pretty-printed XML format with indents and line breaks for easier reading. * * @param xml the XML string to be formatted * @param transferType the type the given XML string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet}. * @return the formatted XML string */ public static String formatXml(final String xml, final Type transferType) { return toXml(fromXml(xml, transferType), Utils.xscPrettyFormat); } /** * Formats the given XML string to its pretty-printed XML format with indents and line breaks for easier reading with the specified {@code XMLSerializationConfig}. * * @param xml the XML string to be formatted * @param config the XML serialization configuration * @return the formatted XML string */ public static String formatXml(final String xml, final XMLSerializationConfig config) { return formatXml(xml, config, MapEntity.class); } /** * Formats the given XML string to its pretty-printed XML format with indents and line breaks for easier reading with the specified {@code XMLSerializationConfig} * * @param xml the XML string to be formatted * @param config the XML serialization configuration * @param transferType the type the given XML string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet}. * @return the formatted XML string */ public static String formatXml(final String xml, final XMLSerializationConfig config, final Class transferType) { final XMLSerializationConfig configToUse = config == null ? Utils.xscPrettyFormat : (!config.prettyFormat() ? config.copy().prettyFormat(true) : config); return toXml(fromXml(xml, transferType), configToUse); } /** * Formats the given XML string to its pretty-printed XML format with indents and line breaks for easier reading with the specified {@code XMLSerializationConfig} * * @param xml the XML string to be formatted * @param config the XML serialization configuration * @param transferType the type the given XML string will be deserialized to. It can be the {@code Type} of {@code Bean/Array/Collection/Map/DataSet}. * @return the formatted XML string */ public static String formatXml(final String xml, final XMLSerializationConfig config, final Type transferType) { final XMLSerializationConfig configToUse = config == null ? Utils.xscPrettyFormat : (!config.prettyFormat() ? config.copy().prettyFormat(true) : config); return toXml(fromXml(xml, transferType), configToUse); } /** * Converts the given XML string to its JSON string representation. * * @param xml the XML string to be converted to JSON * @return the JSON string representation in the given XML */ public static String xml2Json(final String xml) { return xml2Json(xml, Map.class); } /** * Converts the given XML string to its JSON string representation. * * @param xml the XML string to be converted to JSON * @param transferType the type of intermediate object the given XML string will be deserialized for conversion. It only can be the {@code Type} of {@code Bean/Map}. * @return the JSON string representation in the given XML */ public static String xml2Json(final String xml, final Class transferType) { return Utils.jsonParser.serialize(Utils.xmlParser.deserialize(xml, transferType), Utils.jsc); } /** * Converts the given JSON string to its XML string representation. * * @param json the JSON string to be converted to XML * @return the XML string representation in the given JSON */ public static String json2Xml(final String json) { return json2Xml(json, Map.class); } /** * Converts the given JSON string to its XML string representation. * * @param json the JSON string to be converted to XML * @param transferType the type of intermediate object the given JSON string will be deserialized for conversion. It only can be the {@code Type} of {@code Bean/Map}. * @return the XML string representation in the given JSON */ public static String json2Xml(final String json, final Class transferType) { return Utils.xmlParser.serialize(Utils.jsonParser.deserialize(json, transferType)); } /** * Executes the provided {@code action} for each value in the range defined by {@code startInclusive} and {@code endExclusive}. * * @param the type of the exception that the action may throw * @param startInclusive the start value of the range (inclusive) * @param endExclusive the end value of the range (exclusive) * @param action the action to be performed for each value in the range * @throws E if the action throws an exception */ public static void forEach(final int startInclusive, final int endExclusive, final Throwables.Runnable action) throws E { forEach(startInclusive, endExclusive, 1, action); } /** * Executes the provided {@code action} for each value in the range defined by {@code startInclusive}, {@code endExclusive} and {@code step}. * * @param the type of the exception that the action may throw * @param startInclusive the start value of the range (inclusive) * @param endExclusive the end value of the range (exclusive) * @param step the increment value for each iteration in the range. It can be positive or negative but not zero. * @param action the action to be performed for each value in the range * @throws IllegalArgumentException if the step is zero * @throws E if the action throws an exception */ public static void forEach(final int startInclusive, final int endExclusive, final int step, final Throwables.Runnable action) throws IllegalArgumentException, E { checkArgument(step != 0, "The input parameter 'step' can not be zero"); //NOSONAR if (endExclusive == startInclusive || endExclusive > startInclusive != step > 0) { return; } long len = ((long) endExclusive - startInclusive) / step + (((long) endExclusive - startInclusive) % step == 0 ? 0 : 1); while (len-- > 0) { action.run(); } } /** * Executes the provided {@code action} for each value in the range defined by {@code startInclusive} and {@code endExclusive}. * * @param startInclusive the start value of the range (inclusive) * @param endExclusive the end value of the range (exclusive) * @param action the action to be performed for each value in the range * @param the type of the exception that the action may throw * @throws E if the action throws an exception */ public static void forEach(final int startInclusive, final int endExclusive, final Throwables.IntConsumer action) throws E { forEach(startInclusive, endExclusive, 1, action); } /** * Executes the provided {@code action} for each value in the range defined by {@code startInclusive}, {@code endExclusive} and {@code step}. * * @param startInclusive the start value of the range (inclusive) * @param endExclusive the end value of the range (exclusive) * @param step the increment value for each iteration in the range. It can be positive or negative but not zero. * @param action the action to be performed for each value in the range * @param the type of the exception that the action may throw * @throws IllegalArgumentException if the step is zero * @throws E if the action throws an exception */ public static void forEach(final int startInclusive, final int endExclusive, final int step, final Throwables.IntConsumer action) throws E { checkArgument(step != 0, "The input parameter 'step' can not be zero"); if (endExclusive == startInclusive || endExclusive > startInclusive != step > 0) { return; } long len = ((long) endExclusive - startInclusive) / step + (((long) endExclusive - startInclusive) % step == 0 ? 0 : 1); int start = startInclusive; while (len-- > 0) { action.accept(start); start += step; } } /** * Executes the provided {@code action} for each value in the range defined by {@code startInclusive} and {@code endExclusive}, passing the current index and the provided object {@code a} to the action. * * @param the type of the object passed to the action * @param the type of the exception that the action may throw * @param startInclusive the start value of the range (inclusive) * @param endExclusive the end value of the range (exclusive) * @param a the object to be passed to the action * @param action the action to be performed for each value in the range * @throws E if the action throws an exception */ public static void forEach(final int startInclusive, final int endExclusive, final T a, final Throwables.IntObjConsumer action) throws E { forEach(startInclusive, endExclusive, 1, a, action); } /** * Executes the provided {@code action} for each value in the range defined by {@code startInclusive}, {@code endExclusive} and {@code step}, passing the current index and the provided object {@code a} to the action. * * @param the type of the object passed to the action * @param the type of the exception that the action may throw * @param startInclusive the start value of the range (inclusive) * @param endExclusive the end value of the range (exclusive) * @param step the increment value for each iteration in the range. It can be positive or negative but not zero. * @param a the object to be passed to the action * @param action the action to be performed for each value in the range * @throws IllegalArgumentException if the step is zero * @throws E if the action throws an exception */ public static void forEach(final int startInclusive, final int endExclusive, final int step, final T a, final Throwables.IntObjConsumer action) throws E { checkArgument(step != 0, "The input parameter 'step' can not be zero"); if (endExclusive == startInclusive || endExclusive > startInclusive != step > 0) { return; } long len = ((long) endExclusive - startInclusive) / step + (((long) endExclusive - startInclusive) % step == 0 ? 0 : 1); int start = startInclusive; while (len-- > 0) { action.accept(start, a); start += step; } } /** * Executes the provided {@code action} for each element in the given array. * * @param the type of the elements in the array * @param the type of the exception that the action may throw * @param a the array whose elements are to be processed * @param action the action to be performed for each element in the array * @throws E if the action throws an exception */ public static void forEach(final T[] a, final Throwables.Consumer action) throws E { if (isEmpty(a)) { return; } for (final T e : a) { action.accept(e); } } /** * Executes the provided {@code action} for each element within the specified range in the given array. * * @param the type of the elements in the array * @param the type of the exception that the action may throw * @param a the array whose elements are to be processed * @param fromIndex the start index of the range (inclusive) * @param toIndex the end index of the range (exclusive) * @param action the action to be performed for each element within the specified range of the array * @throws IndexOutOfBoundsException if the specified range is out of bounds * @throws E if the action throws an exception */ public static void forEach(final T[] a, final int fromIndex, final int toIndex, final Throwables.Consumer action) throws IndexOutOfBoundsException, E { checkFromToIndex(fromIndex < toIndex ? fromIndex : (toIndex == -1 ? 0 : toIndex), Math.max(fromIndex, toIndex), len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return; } if (fromIndex <= toIndex) { for (int i = fromIndex; i < toIndex; i++) { action.accept(a[i]); } } else { for (int i = min(a.length - 1, fromIndex); i > toIndex; i--) { action.accept(a[i]); } } } /** * Executes the provided {@code action} for each element in the given iterable. * * @param the type of the elements in the iterable * @param the type of the exception that the action may throw * @param c the iterable whose elements are to be processed * @param action the action to be performed for each element in the iterable * @throws E if the action throws an exception */ public static void forEach(final Iterable c, final Throwables.Consumer action) throws E { if (c == null) { return; } for (final T e : c) { action.accept(e); } } /** * Executes the provided {@code action} for each element in the given iterator. * * @param the type of the elements in the iterator * @param the type of the exception that the action may throw * @param iter the iterator whose elements are to be processed * @param action the action to be performed for each element in the iterator * @throws E if the action throws an exception */ public static void forEach(final Iterator iter, final Throwables.Consumer action) throws E { if (iter == null) { return; } while (iter.hasNext()) { action.accept(iter.next()); } } /** * Executes the provided {@code action} for each element within the specified range in the given collection. * * @param the type of the elements in the collection * @param the type of the exception that the action may throw * @param c the collection whose elements are to be processed * @param fromIndex the start index of the range (inclusive) * @param toIndex the end index of the range (exclusive) * @param action the action to be performed for each element within the specified range of the collection * @throws IndexOutOfBoundsException if the specified range is out of bounds * @throws E if the action throws an exception */ public static void forEach(final Collection c, int fromIndex, final int toIndex, final Throwables.Consumer action) throws IndexOutOfBoundsException, E { checkFromToIndex(fromIndex < toIndex ? fromIndex : (toIndex == -1 ? 0 : toIndex), Math.max(fromIndex, toIndex), size(c)); if ((isEmpty(c) && fromIndex == 0 && toIndex == 0) || fromIndex == toIndex) { return; } fromIndex = min(c.size() - 1, fromIndex); if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; if (fromIndex <= toIndex) { for (int i = fromIndex; i < toIndex; i++) { action.accept(list.get(i)); } } else { for (int i = fromIndex; i > toIndex; i--) { action.accept(list.get(i)); } } } else { if (fromIndex <= toIndex) { final Iterator iter = c.iterator(); int idx = 0; while (idx < fromIndex && iter.hasNext()) { iter.next(); idx++; } while (iter.hasNext()) { action.accept(iter.next()); if (++idx >= toIndex) { break; } } } else { final Iterator descendingIterator = getDescendingIteratorIfPossible(c); if (descendingIterator != null) { int idx = c.size() - 1; while (idx > fromIndex && descendingIterator.hasNext()) { descendingIterator.next(); idx--; } while (descendingIterator.hasNext()) { action.accept(descendingIterator.next()); if (--idx <= toIndex) { break; } } } else { final Iterator iter = c.iterator(); int idx = 0; while (idx <= toIndex && iter.hasNext()) { iter.next(); idx++; } final T[] a = (T[]) new Object[fromIndex - toIndex]; while (iter.hasNext()) { a[idx - 1 - toIndex] = iter.next(); if (idx++ >= fromIndex) { break; } } for (int i = a.length - 1; i >= 0; i--) { action.accept(a[i]); } } } } } /** * Executes the provided {@code action} for each entry in the given map. * * @param the type of the keys in the map * @param the type of the values in the map * @param the type of the exception that the action may throw * @param map the map whose elements are to be processed * @param action the action to be performed for each entry in the given map * @throws E if the action throws an exception */ public static void forEach(final Map map, final Throwables.Consumer, E> action) throws E { if (isEmpty(map)) { return; } forEach(map.entrySet(), action); } /** * Executes the provided {@code action} for each entry in the given map. * * @param the type of the keys in the map * @param the type of the values in the map * @param the type of the exception that the action may throw * @param map the map whose elements are to be processed * @param action the action to be performed for each entry in the given map * @throws E if the action throws an exception */ public static void forEach(final Map map, final Throwables.BiConsumer action) throws E { if (isEmpty(map)) { return; } for (final Map.Entry entry : map.entrySet()) { action.accept(entry.getKey(), entry.getValue()); } } /** * Executes the provided {@code elementConsumer} for each element in the given iterable by the specified number of threads. * * @param the type of the elements in the iterable * @param the type of the exception that the elementConsumer may throw * @param c the iterable whose elements are to be processed * @param elementConsumer the action to be performed for each element in the iterable * @param processThreadNum the number of threads to use for processing */ public static void forEach(final Iterable c, final Throwables.Consumer elementConsumer, final int processThreadNum) { forEach(c, elementConsumer, processThreadNum, N.ASYNC_EXECUTOR.getExecutor()); } /** * Executes the provided {@code elementConsumer} for each element in the given iterable by the specified number of threads and executor. * * @param the type of the elements in the iterable * @param the type of the exception that the elementConsumer may throw * @param c the iterable whose elements are to be processed * @param elementConsumer the action to be performed for each element in the iterable * @param processThreadNum the number of threads to use for processing * @param executor the executor to use for processing */ public static void forEach(final Iterable c, final Throwables.Consumer elementConsumer, final int processThreadNum, final Executor executor) { final int size = c instanceof Collection ? ((Collection) c).size() : Integer.MAX_VALUE; forEach(isEmptyCollection(c) ? ObjIterator. empty() : c.iterator(), elementConsumer, N.min(size, processThreadNum), executor); } /** * Executes the provided {@code elementConsumer} for each element in the given iterator by the specified number of threads. * * @param the type of the elements in the iterator * @param the type of the exception that the elementConsumer may throw * @param iter the iterator whose elements are to be processed * @param elementConsumer the action to be performed for each element in the iterator * @param processThreadNum the number of threads to use for processing */ public static void forEach(final Iterator iter, final Throwables.Consumer elementConsumer, final int processThreadNum) { forEach(iter, elementConsumer, processThreadNum, N.ASYNC_EXECUTOR.getExecutor()); } /** * Executes the provided {@code elementConsumer} for each element in the given iterator by the specified number of threads and executor. * * @param the type of the elements in the iterator * @param the type of the exception that the elementConsumer may throw * @param iter the iterator whose elements are to be processed * @param elementConsumer the action to be performed for each element in the iterator * @param processThreadNum the number of threads to use for processing * @param executor the executor to use for processing */ public static void forEach(final Iterator iter, final Throwables.Consumer elementConsumer, final int processThreadNum, final Executor executor) { final Iterator iteratorII = iter == null ? ObjIterator.empty() : iter; final CountDownLatch countDownLatch = new CountDownLatch(processThreadNum); final Holder errorHolder = new Holder<>(); for (int i = 0; i < processThreadNum; i++) { executor.execute(() -> { T element = null; try { while (errorHolder.value() == null) { synchronized (iteratorII) { if (iteratorII.hasNext()) { element = iteratorII.next(); } else { break; } } elementConsumer.accept(element); } } catch (final Exception e) { synchronized (errorHolder) { if (errorHolder.value() == null) { errorHolder.setValue(e); } else { errorHolder.value().addSuppressed(e); } } } finally { countDownLatch.countDown(); } }); } try { countDownLatch.await(); } catch (final InterruptedException e) { throw ExceptionUtil.toRuntimeException(e, true); } if (errorHolder.value() != null) { throw ExceptionUtil.toRuntimeException(errorHolder.value(), true); } } // commented out because of ambiguous and not be consistent with other forEach methods because it has return values. // /** // * Returns a result list kept the same order as the input {@code Iterable/Iterator}. // * // * @param // * @param // * @param // * @param c // * @param elementMapper // * @param processThreadNum // * @see {@link Fnn#f(com.landawn.abacus.util.Throwables.Function) // * @see {@link Fnn#c(com.landawn.abacus.util.Throwables.Consumer)} // */ // @Beta // public static List forEach(final Iterable c, final Throwables.Function elementMapper, // final int processThreadNum) { // return forEach(c, elementMapper, processThreadNum, N.ASYNC_EXECUTOR.getExecutor()); // } // // /** // * Returns a result list kept the same order as the input {@code Iterable/Iterator}. // * // * @param // * @param // * @param // * @param c // * @param elementMapper // * @param processThreadNum // * @param executor // * @see {@link Fnn#f(com.landawn.abacus.util.Throwables.Function) // * @see {@link Fnn#c(com.landawn.abacus.util.Throwables.Consumer)} // */ // @Beta // public static List forEach(final Iterable c, final Throwables.Function elementMapper, // final int processThreadNum, final Executor executor) { // final int size = c instanceof Collection ? ((Collection) c).size() : Integer.MAX_VALUE; // // return forEach(c == null ? ObjIterator. empty() : c.iterator(), elementMapper, N.min(size, processThreadNum), executor); // } // // /** // * Returns a result list kept the same order as the input {@code Iterable/Iterator}. // * // * @param // * @param // * @param // * @param iter // * @param elementConsumer // * @param processThreadNum // * @see {@link Fnn#f(com.landawn.abacus.util.Throwables.Function) // * @see {@link Fnn#c(com.landawn.abacus.util.Throwables.Consumer)} // */ // @Beta // public static List forEach(final Iterator iter, final Throwables.Function elementMapper, // final int processThreadNum) { // return forEach(iter, elementMapper, processThreadNum, N.ASYNC_EXECUTOR.getExecutor()); // } // // /** // * Returns a result list kept the same order as the input {@code Iterable/Iterator}. // * // * @param // * @param // * @param // * @param iter // * @param elementMapper // * @param processThreadNum // * @see {@link Fnn#f(com.landawn.abacus.util.Throwables.Function) // * @see {@link Fnn#c(com.landawn.abacus.util.Throwables.Consumer)} // */ // @Beta // public static List forEach(final Iterator iter, final Throwables.Function elementMapper, // final int processThreadNum, final Executor executor) { // final Iterator iterToUse = iter == null ? ObjIterator. empty() : iter; // final CountDownLatch latch = new CountDownLatch(processThreadNum); // final AtomicInteger index = new AtomicInteger(0); // final Holder errorHolder = new Holder<>(); // final List> result = new ArrayList<>(); // // for (int i = 0; i < processThreadNum; i++) { // executor.execute(() -> { // int idx = 0; // T element = null; // R ret = null; // // try { // while (errorHolder.value() == null) { // synchronized (iterToUse) { // if (iterToUse.hasNext()) { // idx = index.getAndIncrement(); // element = iterToUse.next(); // } else { // break; // } // } // // ret = elementMapper.apply(element); // // synchronized (result) { // result.add(Indexed.of(ret, idx)); // } // } // } catch (Exception e) { // synchronized (errorHolder) { // if (errorHolder.value() == null) { // errorHolder.setValue(e); // } else { // errorHolder.value().addSuppressed(e); // } // } // } finally { // latch.countDown(); // } // }); // } // // try { // latch.await(); // } catch (InterruptedException e) { // ExceptionUtil.toRuntimeException(e, true); // } // // if (errorHolder.value() != null) { // throw ExceptionUtil.toRuntimeException(errorHolder.value()); // } // // N.sort(result, Comparators.comparingInt(Indexed::index)); // // return N.map(result, Indexed::value); // } /** * Applies the provided {@code flatMapper} function to each element in the given array, and then executes the specified {@code action} to each resulting element. * * @param the type of the elements in the array * @param the type of the elements produced by the flatMapper * @param the type of the exception that the flatMapper may throw * @param the type of the exception that the action may throw * @param a the array whose elements are to be processed * @param flatMapper the function to apply to each element in the given array, producing an iterable of elements * @param action the action to be performed for each pair of elements from the given array and the resulting iterable * @throws E if the flatMapper throws an exception * @throws E2 if the action throws an exception */ public static void forEach(final T[] a, final Throwables.Function, E> flatMapper, final Throwables.BiConsumer action) throws E, E2 { if (isEmpty(a)) { return; } for (final T t : a) { final Iterable c2 = flatMapper.apply(t); if (c2 != null) { for (final U u : c2) { action.accept(t, u); } } } } /** * Applies the provided {@code flatMapper} function to each element in the given iterable, and then executes the specified {@code action} to each resulting element. * * @param the type of the elements in the collection * @param the type of the elements produced by the flatMapper * @param the type of the exception that the flatMapper may throw * @param the type of the exception that the action may throw * @param c the collection whose elements are to be processed * @param flatMapper the function to apply to each element in the given iterable, producing an iterable of elements * @param action the action to be performed for each pair of elements from the given iterable and the resulting iterable * @throws E if the flatMapper throws an exception * @throws E2 if the action throws an exception */ public static void forEach(final Iterable c, final Throwables.Function, E> flatMapper, final Throwables.BiConsumer action) throws E, E2 { if (isEmptyCollection(c)) { return; } for (final T t : c) { final Iterable c2 = flatMapper.apply(t); if (c2 != null) { for (final U u : c2) { action.accept(t, u); } } } } /** * Applies the provided {@code flatMapper} function to each element in the given iterator, and then executes the specified {@code action} to each resulting element. * * @param the type of the elements in the iterator * @param the type of the elements produced by the flatMapper * @param the type of the exception that the flatMapper may throw * @param the type of the exception that the action may throw * @param iter the iterator whose elements are to be processed * @param flatMapper the function to apply to each element in the given iterator, producing an iterable of elements * @param action the action to be performed each pair of elements from the given iterator and the resulting iterable * @throws E if the flatMapper throws an exception * @throws E2 if the action throws an exception */ public static void forEach(final Iterator iter, final Throwables.Function, E> flatMapper, final Throwables.BiConsumer action) throws E, E2 { if (iter == null) { return; } T t = null; while (iter.hasNext()) { t = iter.next(); final Iterable c2 = flatMapper.apply(t); if (c2 != null) { for (final U u : c2) { action.accept(t, u); } } } } /** * Executes the provided {@code action} for each element in the given array after applying the {@code flatMapper} and {@code flatMapper2} functions. * The {@code flatMapper} function maps each element of type {@code T} to an {@code Iterable} of elements of type {@code T2}. * The {@code flatMapper2} function maps each element of type {@code T2} to an {@code Iterable} of elements of type {@code T3}. * The {@code action} is then performed for each triple of elements from the original array and the resulting iterables. * * @param the type of the elements in the array * @param the type of the elements in the iterable returned by the flatMapper * @param the type of the elements in the iterable returned by the flatMapper2 * @param the type of the exception that the flatMapper may throw * @param the type of the exception that the flatMapper2 may throw * @param the type of the exception that the action may throw * @param a the array whose elements are to be processed * @param flatMapper the function to apply to each element in given the array to produce an iterable of elements of type T2 * @param flatMapper2 the function to apply to each element in the iterable of type T2 to produce an iterable of elements of type T3 * @param action the action to be performed for each triple of elements from the given array and the resulting iterables * @throws E if the flatMapper throws an exception * @throws E2 if the flatMapper2 throws an exception * @throws E3 if the action throws an exception */ public static void forEach(final T[] a, final Throwables.Function, E> flatMapper, final Throwables.Function, E2> flatMapper2, final Throwables.TriConsumer action) throws E, E2, E3 { if (isEmpty(a)) { return; } for (final T t : a) { final Iterable c2 = flatMapper.apply(t); if (c2 != null) { for (final T2 t2 : c2) { final Iterable c3 = flatMapper2.apply(t2); if (c3 != null) { for (final T3 t3 : c3) { action.accept(t, t2, t3); } } } } } } /** * Executes the provided {@code action} for each element in the given iterable after applying the {@code flatMapper} and {@code flatMapper2} functions. * The {@code flatMapper} function maps each element of type {@code T} to an {@code Iterable} of elements of type {@code T2}. * The {@code flatMapper2} function maps each element of type {@code T2} to an {@code Iterable} of elements of type {@code T3}. * The {@code action} is then performed for each triple of elements from the original iterable and the resulting iterables. * * @param the type of the elements in the collection * @param the type of the elements in the iterable returned by the flatMapper * @param the type of the elements in the iterable returned by the flatMapper2 * @param the type of the exception that the flatMapper may throw * @param the type of the exception that the flatMapper2 may throw * @param the type of the exception that the action may throw * @param c the collection whose elements are to be processed * @param flatMapper the function to apply to each element in the given iterable to produce an iterable of elements of type T2 * @param flatMapper2 the function to apply to each element in the iterable of type T2 to produce an iterable of elements of type T3 * @param action the action to be performed for each triple of elements from the given iterable and the resulting iterables * @throws E if the flatMapper throws an exception * @throws E2 if the flatMapper2 throws an exception * @throws E3 if the action throws an exception */ public static void forEach(final Iterable c, final Throwables.Function, E> flatMapper, final Throwables.Function, E2> flatMapper2, final Throwables.TriConsumer action) throws E, E2, E3 { if (isEmptyCollection(c)) { return; } for (final T t : c) { final Iterable c2 = flatMapper.apply(t); if (c2 != null) { for (final T2 t2 : c2) { final Iterable c3 = flatMapper2.apply(t2); if (c3 != null) { for (final T3 t3 : c3) { action.accept(t, t2, t3); } } } } } } /** * Executes the provided {@code action} for each element in the given iterator after applying the {@code flatMapper} and {@code flatMapper2} functions. * The {@code flatMapper} function maps each element of type {@code T} to an {@code Iterable} of elements of type {@code T2}. * The {@code flatMapper2} function maps each element of type {@code T2} to an {@code Iterable} of elements of type {@code T3}. * The {@code action} is then performed for each triple of elements from the original iterator and the resulting iterables. * * @param the type of the elements in the iterator * @param the type of the elements in the iterable returned by the flatMapper * @param the type of the elements in the iterable returned by the flatMapper2 * @param the type of the exception that the flatMapper may throw * @param the type of the exception that the flatMapper2 may throw * @param the type of the exception that the action may throw * @param iter the iterator whose elements are to be processed * @param flatMapper the function to apply to each element in the given iterator to produce an iterable of elements of type T2 * @param flatMapper2 the function to apply to each element in the iterable of type T2 to produce an iterable of elements of type T3 * @param action the action to be performed for each triple of elements from the given iterator and the resulting iterables * @throws E if the flatMapper throws an exception * @throws E2 if the flatMapper2 throws an exception * @throws E3 if the action throws an exception */ public static void forEach(final Iterator iter, final Throwables.Function, E> flatMapper, final Throwables.Function, E2> flatMapper2, final Throwables.TriConsumer action) throws E, E2, E3 { if (iter == null) { return; } T t = null; while (iter.hasNext()) { t = iter.next(); final Iterable c2 = flatMapper.apply(t); if (c2 != null) { for (final T2 t2 : c2) { final Iterable c3 = flatMapper2.apply(t2); if (c3 != null) { for (final T3 t3 : c3) { action.accept(t, t2, t3); } } } } } } /** * Executes the provided {@code action} for each pair of elements from the given arrays until all elements from the shorter array are processed. * * @param the type of the elements in the first array * @param the type of the elements in the second array * @param the type of the exception that the action may throw * @param a the first array whose elements are to be processed * @param b the second array whose elements are to be processed * @param action the action to be performed for each pair of elements from the arrays * @throws E if the action throws an exception */ public static void forEach(final A[] a, final B[] b, final Throwables.BiConsumer action) throws E { if (isEmpty(a) || isEmpty(b)) { return; } for (int i = 0, minLen = min(a.length, b.length); i < minLen; i++) { action.accept(a[i], b[i]); } } /** * Executes the provided {@code action} for each pair of elements from the given iterables until all elements from the shorter iterable are processed. * * @param the type of the elements in the first iterable * @param the type of the elements in the second iterable * @param the type of the exception that the action may throw * @param a the first iterable whose elements are to be processed * @param b the second iterable whose elements are to be processed * @param action the action to be performed for each pair of elements from the iterables * @throws E if the action throws an exception */ public static void forEach(final Iterable a, final Iterable b, final Throwables.BiConsumer action) throws E { if (isEmptyCollection(a) || isEmptyCollection(b)) { return; } final Iterator iterA = a.iterator(); final Iterator iterB = b.iterator(); forEach(iterA, iterB, action); } /** * Executes the provided {@code action} for each pair of elements from the given iterators until all elements from the shorter iterator are processed. * * @param the type of the elements in the first iterator * @param the type of the elements in the second iterator * @param the type of the exception that the action may throw * @param a the first iterator whose elements are to be processed * @param b the second iterator whose elements are to be processed * @param action the action to be performed for each pair of elements from the iterators * @throws E if the action throws an exception */ public static void forEach(final Iterator a, final Iterator b, final Throwables.BiConsumer action) throws E { if (a == null || b == null) { return; } while (a.hasNext() && b.hasNext()) { action.accept(a.next(), b.next()); } } /** * Executes the provided {@code action} for each triple of elements from the given arrays until all elements from the shortest array are processed. * * @param the type of the elements in the first array * @param the type of the elements in the second array * @param the type of the exception that the action may throw * @param a the first array whose elements are to be processed * @param b the second array whose elements are to be processed * @param c the third array whose elements are to be processed * @param action the action to be performed for each triple of elements from the arrays * @throws E if the action throws an exception */ public static void forEach(final A[] a, final B[] b, final C[] c, final Throwables.TriConsumer action) throws E { if (isEmpty(a) || isEmpty(b) || isEmpty(c)) { return; } for (int i = 0, minLen = min(a.length, b.length, c.length); i < minLen; i++) { action.accept(a[i], b[i], c[i]); } } /** * Executes the provided {@code action} for each triple of elements from the given iterables until all elements from the shortest iterable are processed. * * @param the type of the elements in the first iterable * @param the type of the elements in the second iterable * @param the type of the elements in the third iterable * @param the type of the exception that the action may throw * @param a the first iterable whose elements are to be processed * @param b the second iterable whose elements are to be processed * @param c the third iterable whose elements are to be processed * @param action the action to be performed for each triple of elements from the iterables * @throws E if the action throws an exception */ public static void forEach(final Iterable a, final Iterable b, final Iterable c, final Throwables.TriConsumer action) throws E { if (isEmptyCollection(a) || isEmptyCollection(b) || isEmptyCollection(c)) { return; } final Iterator iterA = a.iterator(); final Iterator iterB = b.iterator(); final Iterator iterC = c.iterator(); forEach(iterA, iterB, iterC, action); } /** * Executes the provided {@code action} for each triple of elements from the given iterators until all elements from the shortest iterator are processed. * * @param the type of the elements in the first iterator * @param the type of the elements in the second iterator * @param the type of the elements in the third iterator * @param the type of the exception that the action may throw * @param a the first iterator whose elements are to be processed * @param b the second iterator whose elements are to be processed * @param c the third iterator whose elements are to be processed * @param action the action to be performed for each triple of elements from the iterators * @throws E if the action throws an exception */ public static void forEach(final Iterator a, final Iterator b, final Iterator c, final Throwables.TriConsumer action) throws E { if (a == null || b == null || c == null) { return; } while (a.hasNext() && b.hasNext() && c.hasNext()) { action.accept(a.next(), b.next(), c.next()); } } /** * Executes the provided {@code action} for each pair of elements from the given arrays until all elements from the longer array are processed. * * @param the type of the elements in the first array * @param the type of the elements in the second array * @param the type of the exception that the action may throw * @param a the first array whose elements are to be processed * @param b the second array whose elements are to be processed * @param valueForNoneA the value to be used if the first array is shorter than the second array * @param valueForNoneB the value to be used if the second array is shorter than the first array * @param action the action to be performed for each pair of elements from the arrays * @throws E if the action throws an exception */ public static void forEach(final A[] a, final B[] b, final A valueForNoneA, final B valueForNoneB, final Throwables.BiConsumer action) throws E { final int lenA = len(a); final int lenB = len(b); for (int i = 0, maxLen = max(lenA, lenB); i < maxLen; i++) { action.accept(i < lenA ? a[i] : valueForNoneA, i < lenB ? b[i] : valueForNoneB); } } /** * Executes the provided {@code action} for each pair of elements from the given iterables until all elements from the longer iterable are processed. * * @param the type of the elements in the first iterable * @param the type of the elements in the second iterable * @param the type of the exception that the action may throw * @param a the first iterable whose elements are to be processed * @param b the second iterable whose elements are to be processed * @param valueForNoneA the value to be used if the first iterable is shorter than the second iterable * @param valueForNoneB the value to be used if the second iterable is shorter than the first iterable * @param action the action to be performed for each pair of elements from the iterables * @throws E if the action throws an exception */ public static void forEach(final Iterable a, final Iterable b, final A valueForNoneA, final B valueForNoneB, final Throwables.BiConsumer action) throws E { final Iterator iterA = isEmptyCollection(a) ? ObjIterator.empty() : a.iterator(); final Iterator iterB = isEmptyCollection(b) ? ObjIterator.empty() : b.iterator(); forEach(iterA, iterB, valueForNoneA, valueForNoneB, action); } /** * Executes the provided {@code action} for each pair of elements from the given iterators until all elements from the longer iterator are processed. * * @param the type of the elements in the first iterator * @param the type of the elements in the second iterator * @param the type of the exception that the action may throw * @param a the first iterator whose elements are to be processed * @param b the second iterator whose elements are to be processed * @param valueForNoneA the value to be used if the first iterator is shorter than the second iterator * @param valueForNoneB the value to be used if the second iterator is shorter than the first iterator * @param action the action to be performed for each pair of elements from the iterators * @throws E if the action throws an exception */ public static void forEach(final Iterator a, final Iterator b, final A valueForNoneA, final B valueForNoneB, final Throwables.BiConsumer action) throws E { final Iterator iterA = a == null ? ObjIterator.empty() : a; final Iterator iterB = b == null ? ObjIterator.empty() : b; A nextA = null; B nextB = null; while (iterA.hasNext() || iterB.hasNext()) { nextA = iterA.hasNext() ? iterA.next() : valueForNoneA; nextB = iterB.hasNext() ? iterB.next() : valueForNoneB; action.accept(nextA, nextB); } } /** * Executes the provided {@code action} for each triple of elements from the given arrays until all elements from the longest array are processed. * * @param the type of the elements in the first array * @param the type of the elements in the second array * @param the type of the elements in the third array * @param the type of the exception that the action may throw * @param a the first array whose elements are to be processed * @param b the second array whose elements are to be processed * @param c the third array whose elements are to be processed * @param valueForNoneA the value to be used if the first array is shorter than the second and third arrays * @param valueForNoneB the value to be used if the second array is shorter than the first and third arrays * @param valueForNoneC the value to be used if the third array is shorter than the first and second arrays * @param action the action to be performed for each triple of elements from the arrays * @throws E if the action throws an exception */ public static void forEach(final A[] a, final B[] b, final C[] c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final Throwables.TriConsumer action) throws E { final int lenA = len(a); final int lenB = len(b); final int lenC = len(c); for (int i = 0, maxLen = max(lenA, lenB, lenC); i < maxLen; i++) { action.accept(i < lenA ? a[i] : valueForNoneA, i < lenB ? b[i] : valueForNoneB, i < lenC ? c[i] : valueForNoneC); } } /** * Executes the provided {@code action} for each triple of elements from the given iterables until all elements from the longest iterable are processed. * * @param the type of the elements in the first iterable * @param the type of the elements in the second iterable * @param the type of the elements in the third iterable * @param the type of the exception that the action may throw * @param a the first iterable whose elements are to be processed * @param b the second iterable whose elements are to be processed * @param c the third iterable whose elements are to be processed * @param valueForNoneA the value to be used if the first iterable is shorter than the second and third iterables * @param valueForNoneB the value to be used if the second iterable is shorter than the first and third iterables * @param valueForNoneC the value to be used if the third iterable is shorter than the first and second iterables * @param action the action to be performed for each triple of elements from the iterables * @throws E if the action throws an exception */ public static void forEach(final Iterable a, final Iterable b, final Iterable c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final Throwables.TriConsumer action) throws E { final Iterator iterA = isEmptyCollection(a) ? ObjIterator.empty() : a.iterator(); final Iterator iterB = isEmptyCollection(b) ? ObjIterator.empty() : b.iterator(); final Iterator iterC = isEmptyCollection(c) ? ObjIterator.empty() : c.iterator(); forEach(iterA, iterB, iterC, valueForNoneA, valueForNoneB, valueForNoneC, action); } /** * Executes the provided {@code action} for each triple of elements from the given iterators until all elements from the longest iterator are processed. * * @param the type of the elements in the first iterator * @param the type of the elements in the second iterator * @param the type of the elements in the third iterator * @param the type of the exception that the action may throw * @param a the first iterator whose elements are to be processed * @param b the second iterator whose elements are to be processed * @param c the third iterator whose elements are to be processed * @param valueForNoneA the value to be used if the first iterator is shorter than the second and third iterators * @param valueForNoneB the value to be used if the second iterator is shorter than the first and third iterators * @param valueForNoneC the value to be used if the third iterator is shorter than the first and second iterators * @param action the action to be performed for each triple of elements from the iterators * @throws E if the action throws an exception */ public static void forEach(final Iterator a, final Iterator b, final Iterator c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final Throwables.TriConsumer action) throws E { final Iterator iterA = a == null ? ObjIterator.empty() : a; final Iterator iterB = b == null ? ObjIterator.empty() : b; final Iterator iterC = b == null ? ObjIterator.empty() : c; A nextA = null; B nextB = null; C nextC = null; while (iterA.hasNext() || iterB.hasNext() || iterC.hasNext()) { nextA = iterA.hasNext() ? iterA.next() : valueForNoneA; nextB = iterB.hasNext() ? iterB.next() : valueForNoneB; nextC = iterC.hasNext() ? iterC.next() : valueForNoneC; action.accept(nextA, nextB, nextC); } } /** * Executes the provided {@code action} for each {@code non-null} element in the given array. The {@code null} elements are ignored. * * @param the type of the elements in the array * @param the type of the exception that the action may throw * @param a the array whose {@code non-null} elements are to be processed * @param action the action to be performed for each {@code non-null} element in the array * @throws E if the action throws an exception */ public static void forEachNonNull(final T[] a, final Throwables.Consumer action) throws E { if (isEmpty(a)) { return; } for (final T e : a) { if (e != null) { action.accept(e); } } } /** * Executes the provided {@code action} for each {@code non-null} element in the given iterable. The {@code null} elements are ignored. * * @param the type of the elements in the collection * @param the type of the exception that the action may throw * @param c the collection whose {@code non-null} elements are to be processed * @param action the action to be performed for each {@code non-null} element in the collection * @throws E if the action throws an exception */ public static void forEachNonNull(final Iterable c, final Throwables.Consumer action) throws E { if (isEmptyCollection(c)) { return; } for (final T e : c) { if (e != null) { action.accept(e); } } } /** * Executes the provided {@code action} for each {@code non-null} element in the given iterator. The {@code null} elements are ignored. * * @param the type of the elements in the iterator * @param the type of the exception that the action may throw * @param iter the iterator whose {@code non-null} elements are to be processed * @param action the action to be performed for each {@code non-null} element in the iterator * @throws E if the action throws an exception */ public static void forEachNonNull(final Iterator iter, final Throwables.Consumer action) throws E { if (iter == null) { return; } T e = null; while (iter.hasNext()) { if ((e = iter.next()) != null) { action.accept(e); } } } /** * Applies the provided {@code flatMapper} function to each {@code non-null} element in the given array, and then executes the specified {@code action} to each {@code non-null} resulting element. * * @param the type of the elements in the given array * @param the type of the elements produced by the flatMapper * @param the type of the exception that the flatMapper may throw * @param the type of the exception that the action may throw * @param a the array whose elements are to be processed * @param flatMapper the function to apply to each {@code non-null} element in the given array, producing an iterable of elements * @param action the action to be performed for each pair of {@code non-null} elements from the given array and the resulting iterable * @throws E if the flatMapper throws an exception * @throws E2 if the action throws an exception */ public static void forEachNonNull(final T[] a, final Throwables.Function, E> flatMapper, final Throwables.BiConsumer action) throws E, E2 { if (isEmpty(a)) { return; } for (final T t : a) { if (t != null) { final Iterable c2 = flatMapper.apply(t); if (c2 != null) { for (final U u : c2) { if (u != null) { action.accept(t, u); } } } } } } /** * Applies the provided {@code flatMapper} function to each {@code non-null} element in the given iterable, and then executes the specified {@code action} to each {@code non-null} resulting element. * * @param the type of the elements in the given iterable * @param the type of the elements produced by the flatMapper * @param the type of the exception that the flatMapper may throw * @param the type of the exception that the action may throw * @param c the collection whose elements are to be processed * @param flatMapper the function to apply to each {@code non-null} element in the given iterable, producing an iterable of elements * @param action the action to be performed for pair of {@code non-null} elements from the given iterable and the resulting iterable * @throws E if the flatMapper throws an exception * @throws E2 if the action throws an exception */ public static void forEachNonNull(final Iterable c, final Throwables.Function, E> flatMapper, final Throwables.BiConsumer action) throws E, E2 { if (isEmptyCollection(c)) { return; } for (final T t : c) { if (t != null) { final Iterable c2 = flatMapper.apply(t); if (c2 != null) { for (final U u : c2) { if (u != null) { action.accept(t, u); } } } } } } /** * Applies the provided {@code flatMapper} function to each {@code non-null} element in the given iterator, and then executes the specified {@code action} to each {@code non-null} resulting element. * * @param the type of the elements in the given iterator * @param the type of the elements produced by the flatMapper * @param the type of the exception that the flatMapper may throw * @param the type of the exception that the action may throw * @param iter the iterator whose elements are to be processed * @param flatMapper the function to apply to each {@code non-null} element in the given iterator, producing an iterable of elements * @param action the action to be performed for pair of {@code non-null} elements from the given iterator and the resulting iterable * @throws E if the flatMapper throws an exception * @throws E2 if the action throws an exception */ public static void forEachNonNull(final Iterator iter, final Throwables.Function, E> flatMapper, final Throwables.BiConsumer action) throws E, E2 { if (iter == null) { return; } T t = null; while (iter.hasNext()) { t = iter.next(); if (t != null) { final Iterable c2 = flatMapper.apply(t); if (c2 != null) { for (final U u : c2) { if (u != null) { action.accept(t, u); } } } } } } /** * Executes the provided {@code action} for each {@code non-null} element in the given array after applying the {@code flatMapper} and {@code flatMapper2} functions. * The {@code flatMapper} function maps each {@code non-null} element of type {@code T} to an {@code Iterable} of elements of type {@code T2}. * The {@code flatMapper2} function maps each {@code non-null} element of type {@code T2} to an {@code Iterable} of elements of type {@code T3}. * The {@code action} is then performed for each triple of {@code non-null} elements from the original array and the resulting iterables. * * @param the type of the elements in the given array * @param the type of the elements in the iterable returned by the flatMapper * @param the type of the elements in the iterable returned by the flatMapper2 * @param the type of the exception that the flatMapper may throw * @param the type of the exception that the flatMapper2 may throw * @param the type of the exception that the action may throw * @param a the array whose {@code non-null} elements are to be processed * @param flatMapper the function to apply to each {@code non-null} element in the given array to produce an iterable of elements of type T2 * @param flatMapper2 the function to apply to each {@code non-null} element in the iterable of type T2 to produce an iterable of elements of type T3 * @param action the action to be performed for each triple of {@code non-null} elements from the given array and the resulting iterables * @throws E if the flatMapper throws an exception * @throws E2 if the flatMapper2 throws an exception * @throws E3 if the action throws an exception */ public static void forEachNonNull(final T[] a, final Throwables.Function, E> flatMapper, final Throwables.Function, E2> flatMapper2, final Throwables.TriConsumer action) throws E, E2, E3 { if (isEmpty(a)) { return; } for (final T t : a) { if (t != null) { final Iterable c2 = flatMapper.apply(t); if (c2 != null) { for (final T2 t2 : c2) { if (t2 != null) { final Iterable c3 = flatMapper2.apply(t2); if (c3 != null) { for (final T3 t3 : c3) { if (t3 != null) { action.accept(t, t2, t3); } } } } } } } } } /** * Executes the provided {@code action} for each {@code non-null} element in the given iterable after applying the {@code flatMapper} and {@code flatMapper2} functions. * The {@code flatMapper} function maps each {@code non-null} element of type {@code T} to an {@code Iterable} of elements of type {@code T2}. * The {@code flatMapper2} function maps each {@code non-null} element of type {@code T2} to an {@code Iterable} of elements of type {@code T3}. * The {@code action} is then performed for each triple of {@code non-null} elements from the original iterable and the resulting iterables. * * @param the type of the elements in the given iterable * @param the type of the elements in the iterable returned by the flatMapper * @param the type of the elements in the iterable returned by the flatMapper2 * @param the type of the exception that the flatMapper may throw * @param the type of the exception that the flatMapper2 may throw * @param the type of the exception that the action may throw * @param c the iterable whose {@code non-null} elements are to be processed * @param flatMapper the function to apply to each {@code non-null} element in the given iterable to produce an iterable of elements of type T2 * @param flatMapper2 the function to apply to each {@code non-null} element in the given iterable of type T2 to produce an iterable of elements of type T3 * @param action the action to be performed for each triple of {@code non-null} elements from the given iterable and the resulting iterables * @throws E if the flatMapper throws an exception * @throws E2 if the flatMapper2 throws an exception * @throws E3 if the action throws an exception */ public static void forEachNonNull(final Iterable c, final Throwables.Function, E> flatMapper, final Throwables.Function, E2> flatMapper2, final Throwables.TriConsumer action) throws E, E2, E3 { if (isEmptyCollection(c)) { return; } for (final T t : c) { if (t != null) { final Iterable c2 = flatMapper.apply(t); if (c2 != null) { for (final T2 t2 : c2) { if (t2 != null) { final Iterable c3 = flatMapper2.apply(t2); if (c3 != null) { for (final T3 t3 : c3) { if (t3 != null) { action.accept(t, t2, t3); } } } } } } } } } /** * Executes the provided {@code action} for each {@code non-null} element in the given iterator after applying the {@code flatMapper} and {@code flatMapper2} functions. * The {@code flatMapper} function maps each {@code non-null} element of type {@code T} to an {@code Iterable} of elements of type {@code T2}. * The {@code flatMapper2} function maps each {@code non-null} element of type {@code T2} to an {@code Iterable} of elements of type {@code T3}. * The {@code action} is then performed for each triple of {@code non-null} elements from the original iterator and the resulting iterables. * * @param the type of the elements in the given iterator * @param the type of the elements produced by the flatMapper * @param the type of the elements produced by the flatMapper2 * @param the type of the exception that the flatMapper may throw * @param the type of the exception that the flatMapper2 may throw * @param the type of the exception that the action may throw * @param iter the iterator whose {@code non-null} elements are to be processed * @param flatMapper the function to apply to each {@code non-null} element in the given iterator to produce an iterable of elements of type T2 * @param flatMapper2 the function to apply to each {@code non-null} element in the iterable of type T2 to produce an iterable of elements of type T3 * @param action the action to be performed for each triple of {@code non-null} elements from the given iterator and the resulting iterables * @throws E if the flatMapper throws an exception * @throws E2 if the flatMapper2 throws an exception * @throws E3 if the action throws an exception */ public static void forEachNonNull(final Iterator iter, final Throwables.Function, E> flatMapper, final Throwables.Function, E2> flatMapper2, final Throwables.TriConsumer action) throws E, E2, E3 { if (iter == null) { return; } T t = null; while (iter.hasNext()) { t = iter.next(); if (t != null) { final Iterable c2 = flatMapper.apply(t); if (c2 != null) { for (final T2 t2 : c2) { if (t2 != null) { final Iterable c3 = flatMapper2.apply(t2); if (c3 != null) { for (final T3 t3 : c3) { if (t3 != null) { action.accept(t, t2, t3); } } } } } } } } } /** * Executes the provided {@code action} for each element in the given array, passing the index and the element to the action. * * @param the type of the elements in the array * @param the type of the exception that the action may throw * @param a the array whose elements are to be processed * @param action the action to be performed for each element, which takes the index and the element as parameters * @throws E if the action throws an exception */ public static void forEachIndexed(final T[] a, final Throwables.IntObjConsumer action) throws E { if (isEmpty(a)) { return; } forEachIndexed(a, 0, a.length, action); } /** * Executes the provided {@code action} for each element within the specified range in the given array, passing the index and the element to the action. * If {@code fromIndex} is greater than {@code toIndex}, the elements are processed from back to front. * * @param the type of the elements in the array * @param the type of the exception that the action may throw * @param a the array whose elements are to be processed * @param fromIndex the starting index (inclusive) of the range to be processed * @param toIndex the ending index (exclusive) of the range to be processed * @param action the action to be performed for each element within the specified range, which takes the index and the element as parameters * @throws IndexOutOfBoundsException if the specified range is out of bounds * @throws E if the action throws an exception */ public static void forEachIndexed(final T[] a, final int fromIndex, final int toIndex, final Throwables.IntObjConsumer action) throws IndexOutOfBoundsException, E { checkFromToIndex(fromIndex < toIndex ? fromIndex : (toIndex == -1 ? 0 : toIndex), Math.max(fromIndex, toIndex), len(a)); // NOSONAR if (isEmpty(a) || fromIndex == toIndex) { return; } if (fromIndex <= toIndex) { for (int i = fromIndex; i < toIndex; i++) { action.accept(i, a[i]); } } else { for (int i = min(a.length - 1, fromIndex); i > toIndex; i--) { action.accept(i, a[i]); } } } /** * Executes the provided {@code action} for each element within the specified range in the given collection, passing the index and the element to the action. * If {@code fromIndex} is greater than {@code toIndex}, the elements are processed from back to front. * * @param the type of the elements in the collection * @param the type of the exception that the action may throw * @param c the collection whose elements are to be processed * @param fromIndex the starting index (inclusive) of the range to be processed * @param toIndex the ending index (exclusive) of the range to be processed * @param action the action to be performed for each element within the specified range, which takes the index and the element as parameters * @throws IndexOutOfBoundsException if the specified range is out of bounds * @throws E if the action throws an exception */ public static void forEachIndexed(final Collection c, int fromIndex, final int toIndex, final Throwables.IntObjConsumer action) throws IndexOutOfBoundsException, E { checkFromToIndex(fromIndex < toIndex ? fromIndex : (toIndex == -1 ? 0 : toIndex), Math.max(fromIndex, toIndex), size(c)); if ((isEmpty(c) && fromIndex == 0 && toIndex == 0) || fromIndex == toIndex) { return; } fromIndex = min(c.size() - 1, fromIndex); if (c instanceof List && c instanceof RandomAccess) { final List list = (List) c; if (fromIndex <= toIndex) { for (int i = fromIndex; i < toIndex; i++) { action.accept(i, list.get(i)); } } else { for (int i = fromIndex; i > toIndex; i--) { action.accept(i, list.get(i)); } } } else { if (fromIndex < toIndex) { final Iterator iter = c.iterator(); int idx = 0; while (idx < fromIndex && iter.hasNext()) { iter.next(); idx++; } while (iter.hasNext()) { action.accept(idx, iter.next()); if (++idx >= toIndex) { break; } } } else { final Iterator descendingIterator = getDescendingIteratorIfPossible(c); if (descendingIterator != null) { int idx = c.size() - 1; while (idx > fromIndex && descendingIterator.hasNext()) { descendingIterator.next(); idx--; } while (descendingIterator.hasNext()) { action.accept(idx, descendingIterator.next()); if (--idx <= toIndex) { break; } } } else { final Iterator iter = c.iterator(); int idx = 0; while (idx <= toIndex && iter.hasNext()) { iter.next(); idx++; } final T[] a = (T[]) new Object[fromIndex - toIndex]; while (iter.hasNext()) { a[idx - 1 - toIndex] = iter.next(); if (idx++ >= fromIndex) { break; } } for (int i = a.length - 1; i >= 0; i--) { action.accept(i + toIndex + 1, a[i]); } } } } } /** * Executes the provided {@code action} for each element in the given iterable, passing the index and the element to the action. * * @param the type of the elements in the iterable * @param the type of the exception that the action may throw * @param c the collection whose elements are to be processed * @param action the action to be performed for each element, which takes the index and the element as parameters * @throws E if the action throws an exception */ public static void forEachIndexed(final Iterable c, final Throwables.IntObjConsumer action) throws E { if (c == null) { return; } int idx = 0; for (final T e : c) { action.accept(idx++, e); } } /** * Executes the provided {@code action} for each element in the given iterable, passing the index and the element to the action. * * @param the type of the elements in the iterable * @param the type of the exception that the action may throw * @param iter the iterator whose elements are to be processed * @param action the action to be performed for each element, which takes the index and the element as parameters * @throws E if the action throws an exception */ public static void forEachIndexed(final Iterator iter, final Throwables.IntObjConsumer action) throws E { if (iter == null) { return; } int idx = 0; while (iter.hasNext()) { action.accept(idx++, iter.next()); } } /** * Executes the provided {@code action} for each entry in the given map, passing the index and the entry to the action. * * @param the type of the keys in the map * @param the type of the values in the map * @param the type of the exception that the action may throw * @param map the map whose entries are to be processed * @param action the action to be performed for each entry, which takes the index and the entry as parameters * @throws E if the action throws an exception */ public static void forEachIndexed(final Map map, final Throwables.IntObjConsumer, E> action) throws E { if (isEmpty(map)) { return; } forEachIndexed(map.entrySet(), action); } /** * Executes the provided {@code action} for each entry in the given map, passing the index, the key, and the value to the action. * * @param the type of the keys in the map * @param the type of the values in the map * @param the type of the exception that the action may throw * @param map the map whose entries are to be processed * @param action the action to be performed for each entry, which takes the index, the key, and the value as parameters * @throws E if the action throws an exception */ public static void forEachIndexed(final Map map, final Throwables.IntBiObjConsumer action) throws E { if (isEmpty(map)) { return; } int idx = 0; for (final Map.Entry entry : map.entrySet()) { action.accept(idx++, entry.getKey(), entry.getValue()); } } /** * Executes the provided {@code action} for each element in the given {@code Iterable}, passing the index and the element to the action, by the specified number of threads. * * @param the type of the elements in the {@code Iterable} * @param the type of the exception that the consumer may throw * @param c the {@code Iterable} whose elements are to be processed * @param action the consumer to be performed for each element, which takes the index and the element as parameters * @param processThreadNum the number of threads to use for processing * @throws E if the consumer throws an exception */ public static void forEachIndexed(final Iterable c, final Throwables.IntObjConsumer action, final int processThreadNum) { forEachIndexed(c, action, processThreadNum, N.ASYNC_EXECUTOR.getExecutor()); } /** * Executes the provided {@code action} for each element in the given {@code Iterable}, passing the index and the element to the action, by the specified number of threads and executor. * * @param the type of the elements in the {@code Iterable} * @param the type of the exception that the consumer may throw * @param c the {@code Iterable} whose elements are to be processed * @param action the consumer to be performed for each element, which takes the index and the element as parameters * @param processThreadNum the number of threads to use for processing * @param executor the executor to use for processing * @throws E if the consumer throws an exception */ public static void forEachIndexed(final Iterable c, final Throwables.IntObjConsumer action, final int processThreadNum, final Executor executor) { final int size = c instanceof Collection ? ((Collection) c).size() : Integer.MAX_VALUE; forEachIndexed(c == null ? ObjIterator. empty() : c.iterator(), action, N.min(size, processThreadNum), executor); } /** * Executes the provided {@code action} for each element in the given {@code Iterator}, passing the index and the element to the action, by the specified number of threads. * * @param the type of the elements in the {@code Iterator} * @param the type of the exception that the consumer may throw * @param iter the {@code Iterator} whose elements are to be processed * @param elementConsumer the consumer to be performed for each element, which takes the index and the element as parameters * @param processThreadNum the number of threads to use for processing * @throws E if the consumer throws an exception */ public static void forEachIndexed(final Iterator iter, final Throwables.IntObjConsumer elementConsumer, final int processThreadNum) { forEachIndexed(iter, elementConsumer, processThreadNum, N.ASYNC_EXECUTOR.getExecutor()); } /** * Executes the provided {@code action} for each element in the given {@code Iterator}, passing the index and the element to the action, by the specified number of threads and executor. * * @param the type of the elements in the {@code Iterator} * @param the type of the exception that the consumer may throw * @param iter the {@code Iterator} whose elements are to be processed * @param elementConsumer the consumer to be performed for each element, which takes the index and the element as parameters * @param processThreadNum the number of threads to use for processing * @param executor the executor to use for processing * @throws E if the consumer throws an exception */ public static void forEachIndexed(final Iterator iter, final Throwables.IntObjConsumer elementConsumer, final int processThreadNum, final Executor executor) throws IllegalArgumentException { final Iterator iteratorII = iter == null ? ObjIterator.empty() : iter; final CountDownLatch countDownLatch = new CountDownLatch(processThreadNum); final AtomicInteger index = new AtomicInteger(0); final Holder errorHolder = new Holder<>(); for (int i = 0; i < processThreadNum; i++) { executor.execute(() -> { int idx = 0; T element = null; try { while (errorHolder.value() == null) { synchronized (iteratorII) { if (iteratorII.hasNext()) { idx = index.getAndIncrement(); element = iteratorII.next(); } else { break; } } elementConsumer.accept(idx, element); } } catch (final Exception e) { synchronized (errorHolder) { if (errorHolder.value() == null) { errorHolder.setValue(e); } else { errorHolder.value().addSuppressed(e); } } } finally { countDownLatch.countDown(); } }); } try { countDownLatch.await(); } catch (final InterruptedException e) { throw ExceptionUtil.toRuntimeException(e, true); } if (errorHolder.value() != null) { throw ExceptionUtil.toRuntimeException(errorHolder.value(), true); } } // commented out because of ambiguous and not be consistent with other forEach methods because it has return values. // /** // * Returns a result list kept the same order as the input {@code Iterable/Iterator}. // * // * @param // * @param // * @param // * @param c // * @param elementMapper // * @param processThreadNum // * @see Throwables.IntObjFunction#of(com.landawn.abacus.util.Throwables.IntObjFunction) // * @see Throwables.IntObjConsumer#of(com.landawn.abacus.util.Throwables.IntObjConsumer) // */ // @Beta // public static List forEachIndexed(final Iterable c, // final Throwables.IntObjFunction elementMapper, final int processThreadNum) { // return forEachIndexed(c, elementMapper, processThreadNum, N.ASYNC_EXECUTOR.getExecutor()); // } // // /** // * Returns a result list kept the same order as the input {@code Iterable/Iterator}. // * // * @param // * @param // * @param // * @param c // * @param elementMapper // * @param processThreadNum // * @param executor // * @see Throwables.IntObjFunction#of(com.landawn.abacus.util.Throwables.IntObjFunction) // * @see Throwables.IntObjConsumer#of(com.landawn.abacus.util.Throwables.IntObjConsumer) // */ // @Beta // public static List forEachIndexed(final Iterable c, // final Throwables.IntObjFunction elementMapper, final int processThreadNum, final Executor executor) { // final int size = c instanceof Collection ? ((Collection) c).size() : Integer.MAX_VALUE; // // return forEachIndexed(c == null ? ObjIterator. empty() : c.iterator(), elementMapper, N.min(size, processThreadNum), executor); // } // // /** // * Returns a result list kept the same order as the input {@code Iterable/Iterator}. // * // * @param // * @param // * @param // * @param iter // * @param elementConsumer // * @param processThreadNum // * @see Throwables.IntObjFunction#of(com.landawn.abacus.util.Throwables.IntObjFunction) // * @see Throwables.IntObjConsumer#of(com.landawn.abacus.util.Throwables.IntObjConsumer) // */ // @Beta // public static List forEachIndexed(final Iterator iter, // final Throwables.IntObjFunction elementMapper, final int processThreadNum) { // return forEachIndexed(iter, elementMapper, processThreadNum, N.ASYNC_EXECUTOR.getExecutor()); // } // // /** // * Returns a result list kept the same order as the input {@code Iterable/Iterator}. // * // * @param // * @param // * @param // * @param iter // * @param elementMapper // * @param processThreadNum // * @see Throwables.IntObjFunction#of(com.landawn.abacus.util.Throwables.IntObjFunction) // * @see Throwables.IntObjConsumer#of(com.landawn.abacus.util.Throwables.IntObjConsumer) // */ // @Beta // public static List forEachIndexed(final Iterator iter, // final Throwables.IntObjFunction elementMapper, final int processThreadNum, final Executor executor) { // final Iterator iterToUse = iter == null ? ObjIterator. empty() : iter; // final CountDownLatch latch = new CountDownLatch(processThreadNum); // final AtomicInteger index = new AtomicInteger(0); // final Holder errorHolder = new Holder<>(); // final List> result = new ArrayList<>(); // // for (int i = 0; i < processThreadNum; i++) { // executor.execute(() -> { // int idx = 0; // T element = null; // R ret = null; // // try { // while (errorHolder.value() == null) { // synchronized (iterToUse) { // if (iterToUse.hasNext()) { // idx = index.getAndIncrement(); // element = iterToUse.next(); // } else { // break; // } // } // // ret = elementMapper.apply(idx, element); // // synchronized (result) { // result.add(Indexed.of(ret, idx)); // } // } // } catch (Exception e) { // synchronized (errorHolder) { // if (errorHolder.value() == null) { // errorHolder.setValue(e); // } else { // errorHolder.value().addSuppressed(e); // } // } // } finally { // latch.countDown(); // } // }); // } // // try { // latch.await(); // } catch (InterruptedException e) { // ExceptionUtil.toRuntimeException(e, true); // } // // if (errorHolder.value() != null) { // throw ExceptionUtil.toRuntimeException(errorHolder.value()); // } // // N.sort(result, Comparators.comparingInt(Indexed::index)); // // return N.map(result, Indexed::value); // } /** * Executes the provided {@code action} for each pair of consecutive elements in the given array. * For the last non-paired element, the action is performed with the last element and {@code null}. * * @param the type of the elements in the array * @param the type of the exception that the action may throw * @param a the array whose elements are to be processed * @param action the action to be performed for each pair of elements * @throws E if the action throws an exception */ public static void forEachPair(final T[] a, final Throwables.BiConsumer action) throws E { forEachPair(a, 1, action); } /** * Executes the provided {@code action} for each pair of consecutive elements in the given array, with the specified increment between pairs. * For the last non-paired element, the action is performed with the last element and {@code null}. * * @param the type of the elements in the array * @param the type of the exception that the action may throw * @param a the array whose elements are to be processed * @param increment the increment between pairs of elements * @param action the action to be performed for each pair of elements * @throws E if the action throws an exception */ public static void forEachPair(final T[] a, final int increment, final Throwables.BiConsumer action) throws E { checkArgPositive(increment, cs.increment); if (isEmpty(a)) { return; } final Iterator iter = ObjIterator.of(a); forEachPair(iter, increment, action); } /** * Executes the provided {@code action} for each pair of consecutive elements in the given iterable. * For the last non-paired element, the action is performed with the last element and {@code null}. * * @param the type of the elements in the iterable * @param the type of the exception that the action may throw * @param c the iterable whose elements are to be processed * @param action the action to be performed for each pair of elements * @throws E if the action throws an exception */ public static void forEachPair(final Iterable c, final Throwables.BiConsumer action) throws E { forEachPair(c, 1, action); } /** * Executes the provided {@code action} for each pair of consecutive elements in the given iterable, with the specified increment between pairs. * For the last non-paired element, the action is performed with the last element and {@code null}. * * @param the type of the elements in the iterable * @param the type of the exception that the action may throw * @param c the iterable whose elements are to be processed * @param increment the increment between pairs of elements * @param action the action to be performed for each pair of elements * @throws E if the action throws an exception */ public static void forEachPair(final Iterable c, final int increment, final Throwables.BiConsumer action) throws E { checkArgPositive(increment, cs.increment); if (isEmptyCollection(c)) { return; } final Iterator iter = c.iterator(); forEachPair(iter, increment, action); } /** * Executes the provided {@code action} for each pair of consecutive elements in the given iterator. * For the last non-paired element, the action is performed with the last element and {@code null}. * * @param the type of the elements in the iterator * @param the type of the exception that the action may throw * @param iter the iterator whose elements are to be processed * @param action the action to be performed for each pair of elements * @throws E if the action throws an exception */ public static void forEachPair(final Iterator iter, final Throwables.BiConsumer action) throws E { forEachPair(iter, 1, action); } /** * Executes the provided {@code action} for each pair of consecutive elements in the given iterator, with the specified increment between pairs. * For the last non-paired element, the action is performed with the last element and {@code null}. * * @param the type of the elements in the iterator * @param the type of the exception that the action may throw * @param iter the iterator whose elements are to be processed * @param increment the increment between pairs of elements * @param action the action to be performed for each pair of elements * @throws E if the action throws an exception */ public static void forEachPair(final Iterator iter, final int increment, final Throwables.BiConsumer action) throws E { final int windowSize = 2; checkArgPositive(increment, cs.increment); if (iter == null) { return; } boolean isFirst = true; T prev = null; while (iter.hasNext()) { if (increment > windowSize && !isFirst) { int skipNum = increment - windowSize; while (skipNum-- > 0 && iter.hasNext()) { iter.next(); } if (!iter.hasNext()) { break; } } if (increment == 1) { action.accept(isFirst ? iter.next() : prev, (prev = (iter.hasNext() ? iter.next() : null))); } else { action.accept(iter.next(), iter.hasNext() ? iter.next() : null); } isFirst = false; } } /** * Executes the provided {@code action} for each triple of consecutive elements in the given array. * For the last two non-tripled elements, the action is performed with the last two elements and {@code null}. * * @param the type of the elements in the array * @param the type of the exception that the action may throw * @param a the array whose elements are to be processed * @param action the action to be performed for each triple of elements * @throws E if the action throws an exception */ public static void forEachTriple(final T[] a, final Throwables.TriConsumer action) throws E { forEachTriple(a, 1, action); } /** * Executes the provided {@code action} for each triple of consecutive elements in the given array, with the specified increment between triples. * For the last two non-tripled elements, the action is performed with the last two elements and {@code null}. * * @param the type of the elements in the array * @param the type of the exception that the action may throw * @param a the array whose elements are to be processed * @param increment the increment between triples of elements * @param action the action to be performed for each triple of elements * @throws E if the action throws an exception */ public static void forEachTriple(final T[] a, final int increment, final Throwables.TriConsumer action) throws E { checkArgPositive(increment, cs.increment); if (isEmpty(a)) { return; } final Iterator iter = ObjIterator.of(a); forEachTriple(iter, increment, action); } /** * Executes the provided {@code action} for each triple of consecutive elements in the given iterable. * For the last two non-tripled elements, the action is performed with the last two elements and {@code null}. * * @param the type of the elements in the iterable * @param the type of the exception that the action may throw * @param c the iterable whose elements are to be processed * @param action the action to be performed for each triple of elements * @throws E if the action throws an exception */ public static void forEachTriple(final Iterable c, final Throwables.TriConsumer action) throws E { forEachTriple(c, 1, action); } /** * Executes the provided {@code action} for each triple of consecutive elements in the given iterable, with the specified increment between triples. * For the last two non-tripled elements, the action is performed with the last two elements and {@code null}. * * @param the type of the elements in the iterable * @param the type of the exception that the action may throw * @param c the iterable whose elements are to be processed * @param increment the increment between triples of elements * @param action the action to be performed for each triple of elements * @throws E if the action throws an exception */ public static void forEachTriple(final Iterable c, final int increment, final Throwables.TriConsumer action) throws E { checkArgPositive(increment, cs.increment); if (c == null) { return; } final Iterator iter = c.iterator(); forEachTriple(iter, increment, action); } /** * Executes the provided {@code action} for each triple of consecutive elements in the given iterator. * For the last two non-tripled elements, the action is performed with the last two elements and {@code null}. * * @param the type of the elements in the iterator * @param the type of the exception that the action may throw * @param iter the iterator whose elements are to be processed * @param action the action to be performed for each triple of elements * @throws E if the action throws an exception */ public static void forEachTriple(final Iterator iter, final Throwables.TriConsumer action) throws E { forEachTriple(iter, 1, action); } /** * Executes the provided {@code action} for each triple of consecutive elements in the given iterator, with the specified increment between triples. * For the last two non-tripled elements, the action is performed with the last two elements and {@code null}. * * @param the type of the elements in the iterator * @param the type of the exception that the action may throw * @param iter the iterator whose elements are to be processed * @param increment the increment between triples of elements * @param action the action to be performed for each triple of elements * @throws E if the action throws an exception */ public static void forEachTriple(final Iterator iter, final int increment, final Throwables.TriConsumer action) throws E { final int windowSize = 3; checkArgPositive(increment, cs.increment); if (iter == null) { return; } boolean isFirst = true; T prev = null; T prev2 = null; while (iter.hasNext()) { if (increment > windowSize && !isFirst) { int skipNum = increment - windowSize; while (skipNum-- > 0 && iter.hasNext()) { iter.next(); } if (!iter.hasNext()) { break; } } if (increment == 1) { action.accept(isFirst ? iter.next() : prev2, (prev2 = (isFirst ? (iter.hasNext() ? iter.next() : null) : prev)), (prev = (iter.hasNext() ? iter.next() : null))); } else if (increment == 2) { action.accept(isFirst ? iter.next() : prev, iter.hasNext() ? iter.next() : null, (prev = (iter.hasNext() ? iter.next() : null))); } else { action.accept(iter.next(), iter.hasNext() ? iter.next() : null, iter.hasNext() ? iter.next() : null); } isFirst = false; } } /** * Executes the provided command with the specified retry logic in case of failure. * * @param cmd the command to be executed * @param retryTimes the number of times to retry the command if it fails * @param retryIntervalInMillis the interval in milliseconds between retries * @param retryCondition The condition to be checked after each execution failure to decide whether to retry or not * @throws RuntimeException if the command execution fails and no more retries are allowed. * @see Retry#of(int, long, Predicate) * @see Retry#of(int, long, BiPredicate) * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static void execute(final Throwables.Runnable cmd, final int retryTimes, final long retryIntervalInMillis, final Predicate retryCondition) { try { Retry.of(retryTimes, retryIntervalInMillis, retryCondition).run(cmd); } catch (final Exception e) { throw ExceptionUtil.toRuntimeException(e, true); } } /** * Executes the provided command with the specified retry logic in case of failure. * * @param cmd the command to be executed * @param retryTimes the number of times to retry the command if it fails * @param retryIntervalInMillis the interval in milliseconds between retries * @param retryCondition The condition to be checked after each execution failure to decide whether to retry or not * @return The result returned by the Callable task. * @throws RuntimeException if the command execution fails and no more retries are allowed. * @see Retry#of(int, long, Predicate) * @see Retry#of(int, long, BiPredicate) * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static R execute(final Callable cmd, final int retryTimes, final long retryIntervalInMillis, final BiPredicate retryCondition) { try { final Retry retry = Retry.of(retryTimes, retryIntervalInMillis, retryCondition); return retry.call(cmd); } catch (final Exception e) { throw ExceptionUtil.toRuntimeException(e, true); } } /** * Executes the provided command asynchronously. * * @param command the command to be executed * @return a ContinuableFuture representing the pending completion of the task * @see Futures * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static ContinuableFuture asyncExecute(final Throwables.Runnable command) { return ASYNC_EXECUTOR.execute(command); } /** * Executes the provided command asynchronously by the specified executor. * * @param command the command to be executed * @param executor the executor to use for processing * @return a ContinuableFuture representing the pending completion of the task * @see Futures * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static ContinuableFuture asyncExecute(final Throwables.Runnable command, final Executor executor) { return ContinuableFuture.run(command, executor); } /** * Executes the provided command asynchronously with the specified delay. * * @param command the command to be executed * @param delayInMillis The delay before the command is executed, in milliseconds. * @return a ContinuableFuture representing the pending completion of the task * @see Futures * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static ContinuableFuture asyncExecute(final Throwables.Runnable command, final long delayInMillis) { return new ContinuableFuture<>(SCHEDULED_EXECUTOR.schedule(() -> { command.run(); return null; }, delayInMillis, TimeUnit.MILLISECONDS)); } /** * Executes the provided command asynchronously. * * @param command the command to be executed * @return a ContinuableFuture representing the pending completion of the task * @see Futures * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static ContinuableFuture asyncExecute(final Callable command) { return ASYNC_EXECUTOR.execute(command); } /** * Executes the provided command asynchronously by the specified executor. * * @param command the command to be executed * @param executor the executor to use for processing * @return a ContinuableFuture representing the pending completion of the task * @see Futures * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static ContinuableFuture asyncExecute(final Callable command, final Executor executor) { return ContinuableFuture.call(command, executor); } /** * Executes the provided command asynchronously with the specified delay. * * @param command the command to be executed * @param delayInMillis The delay before the command is executed, in milliseconds. * @return a ContinuableFuture representing the pending completion of the task * @see Futures * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static ContinuableFuture asyncExecute(final Callable command, final long delayInMillis) { return new ContinuableFuture<>(SCHEDULED_EXECUTOR.schedule(command, delayInMillis, TimeUnit.MILLISECONDS)); } // /** // * // * @param commands // * @return // * @see Futures // * @see Fn#jr(Runnable) // * @see Fn#jc(Callable) // */ // @SuppressWarnings("deprecation") // @SafeVarargs // public static List> asyncExecute(final Throwables.Runnable... commands) { // return ASYNC_EXECUTOR.execute(commands); // } /** * Executes the provided command asynchronously with the specified retry logic in case of failure. * * @param cmd the command to be executed * @param retryTimes the number of times to retry the command if it fails * @param retryIntervalInMillisInMillis the interval in milliseconds between retries * @param retryCondition The condition to be checked after each execution failure to decide whether to retry or not * @see Retry#of(int, long, Predicate) * @see Retry#of(int, long, BiPredicate) * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static ContinuableFuture asyncExecute(final Throwables.Runnable cmd, final int retryTimes, final long retryIntervalInMillisInMillis, final Predicate retryCondition) { return ASYNC_EXECUTOR.execute(() -> { Retry.of(retryTimes, retryIntervalInMillisInMillis, retryCondition).run(cmd); return null; }); } /** * Executes the provided command asynchronously with the specified retry logic in case of failure. * * @param cmd the command to be executed * @param retryTimes the number of times to retry the command if it fails * @param retryIntervalInMillisInMillis the interval in milliseconds between retries * @param retryCondition The condition to be checked after each execution failure to decide whether to retry or not * @see Retry#of(int, long, Predicate) * @see Retry#of(int, long, BiPredicate) * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static ContinuableFuture asyncExecute(final Callable cmd, final int retryTimes, final long retryIntervalInMillisInMillis, final BiPredicate retryCondition) { return ASYNC_EXECUTOR.execute(() -> { final Retry retry = Retry.of(retryTimes, retryIntervalInMillisInMillis, retryCondition); return retry.call(cmd); }); } /** * Executes the provided a list of commands asynchronously. * * @param commands the list of commands to be executed * @return a list of ContinuableFuture objects representing the pending completion of each command * @see Futures * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static List> asyncExecute(final List> commands) { return ASYNC_EXECUTOR.execute(commands); } /** * Executes the provided a list of commands asynchronously by the specified executor. * * @param commands the list of commands to be executed * @param executor the executor to use for processing * @return a list of ContinuableFuture objects representing the pending completion of each command * @see Futures * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static List> asyncExecute(final List> commands, final Executor executor) { if (isEmpty(commands)) { return new ArrayList<>(); } final List> results = new ArrayList<>(commands.size()); for (final Throwables.Runnable cmd : commands) { results.add(ContinuableFuture.run(cmd, executor)); } return results; } // /** // * // * @param // * @param commands // * @return // * @see Futures // * @see Fn#jr(Runnable) // * @see Fn#jc(Callable) // */ // @SuppressWarnings("deprecation") // @SafeVarargs // public static List> asyncExecute(final Callable... commands) { // return ASYNC_EXECUTOR.execute(commands); // } /** * Executes the provided a collection of commands asynchronously. * * @param commands the collection of commands to be executed * @return a list of ContinuableFuture objects representing the pending completion of each command * @see Futures * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static List> asyncExecute(final Collection> commands) { return ASYNC_EXECUTOR.execute(commands); } /** * Executes the provided a collection of commands asynchronously by the specified executor. * * @param commands the collection of commands to be executed * @param executor the executor to use for processing * @return a list of ContinuableFuture objects representing the pending completion of each command * @see Futures * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static List> asyncExecute(final Collection> commands, final Executor executor) { if (isEmpty(commands)) { return new ArrayList<>(); } final List> results = new ArrayList<>(commands.size()); for (final Callable cmd : commands) { results.add(ContinuableFuture.call(cmd, executor)); } return results; } /** * Executes the specified commands/tasks asynchronously and immediately returns an iterator for iterating the result lazily. * The first element will be the result of the command/task which is completed first. *
* If an error occurs in one command/task, iteration will be interrupted and the error will be thrown. * However, other commands/tasks won't be impacted or cancelled. * * @param commands the collection of commands/tasks to be executed * @return an iterator for iterating the results of the commands/tasks * @see Futures#iterate(Collection) * @see Futures#iterate(Collection, Function) * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static ObjIterator asynRun(final Collection> commands) { return asynRun(commands, ASYNC_EXECUTOR.getExecutor()); } /** * Executes the specified commands/tasks asynchronously by the specified executor and immediately returns an iterator for iterating the result lazily. * The first element will be the result of the command/task which is completed first. *
* If an error occurs in one command/task, iteration will be interrupted and the error will be thrown. * However, other commands/tasks won't be impacted or cancelled. * * @param commands the collection of commands/tasks to be executed * @param executor the executor to use for processing * @return an iterator for iterating the results of the commands/tasks * @see Futures#iterate(Collection) * @see Futures#iterate(Collection, Function) * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static ObjIterator asynRun(final Collection> commands, final Executor executor) { if (isEmpty(commands)) { return ObjIterator.empty(); } final int cmdCount = commands.size(); final List> futures = new LinkedList<>(); final ArrayBlockingQueue queue = new ArrayBlockingQueue<>(cmdCount); for (final Throwables.Runnable cmd : commands) { final FutureTask futureTask = new FutureTask<>(() -> { cmd.run(); queue.add(NULL_MASK); return null; }); executor.execute(futureTask); futures.add(futureTask); } return new ObjIterator<>() { @Override public boolean hasNext() { if (queue.size() > 0) { return true; } while (true) { final Iterator> iter = futures.iterator(); while (iter.hasNext()) { final FutureTask future = iter.next(); if (future.isDone()) { try { future.get(); } catch (InterruptedException | ExecutionException e) { // cause inconsistent if iterate result or not. Secondly, asynchronized execution should not impact each other. // while (iter.hasNext()) { // iter.next().cancel(false); // } throw ExceptionUtil.toRuntimeException(e, true); } iter.remove(); if (queue.size() > 0) { return true; } } } if (queue.size() > 0) { return true; } if (futures.size() == 0) { break; } sleepUninterruptibly(1); } //noinspection ConstantValue return queue.size() > 0; } @Override public Void next() { if (!hasNext()) { throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX); } queue.poll(); return null; } }; } /** * Executes the specified commands/tasks asynchronously and immediately returns an iterator for iterating the result lazily. * The first element will be the result of the command/task which is completed first. *
* If an error occurs in one command/task, iteration will be interrupted and the error will be thrown. * However, other commands/tasks won't be impacted or cancelled. * * @param commands the collection of commands/tasks to be executed * @return an iterator for iterating the results of the commands/tasks * @see Futures#iterate(Collection) * @see Futures#iterate(Collection, Function) * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static ObjIterator asynCall(final Collection> commands) { return asynCall(commands, ASYNC_EXECUTOR.getExecutor()); } /** * Executes the specified commands/tasks asynchronously by the specified executor and immediately returns an iterator for iterating the result lazily. * The first element will be the result of the command/task which is completed first. *
* If an error occurs in one command/task, iteration will be interrupted and the error will be thrown. * However, other commands/tasks won't be impacted or cancelled. * * @param commands the collection of commands/tasks to be executed * @param executor the executor to use for processing * @return an iterator for iterating the results of the commands/tasks * @see Futures#iterate(Collection) * @see Futures#iterate(Collection, Function) * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static ObjIterator asynCall(final Collection> commands, final Executor executor) throws IllegalArgumentException { if (isEmpty(commands)) { return ObjIterator.empty(); } final int cmdCount = commands.size(); final List> futures = new LinkedList<>(); final ArrayBlockingQueue queue = new ArrayBlockingQueue<>(cmdCount); final R none = (R) NULL_MASK; for (final Callable cmd : commands) { final FutureTask futureTask = new FutureTask<>(() -> { final R ret = cmd.call(); if (ret == null) { queue.add(none); } else { queue.add(ret); } return ret; }); executor.execute(futureTask); futures.add(futureTask); } return new ObjIterator<>() { private R next = null; @Override public boolean hasNext() { if (queue.size() > 0) { return true; } while (true) { final Iterator> iter = futures.iterator(); while (iter.hasNext()) { final FutureTask future = iter.next(); if (future.isDone()) { try { future.get(); } catch (InterruptedException | ExecutionException e) { // cause inconsistent if iterate result or not. Secondly, asynchronized execution should not impact each other. // while (iter.hasNext()) { // iter.next().cancel(false); // } throw ExceptionUtil.toRuntimeException(e, true); } iter.remove(); if (queue.size() > 0) { return true; } } } if (queue.size() > 0) { return true; } if (futures.size() == 0) { break; } sleepUninterruptibly(1); } //noinspection ConstantValue return queue.size() > 0; } @Override public R next() { if (!hasNext()) { throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX); } next = queue.poll(); return next == none ? null : next; } }; } /** * Executes and completes the input commands in parallel. *
* If an error occurs in one task, {@code cancel()} will be called for other unfinished tasks. * * @param command the first command to be executed in current thread. * @param command2 the second command to be executed in another thread. * @throws Exception if an error occurs during the execution of any command * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static void runInParallel(final Throwables.Runnable command, final Throwables.Runnable command2) { final ContinuableFuture f2 = asyncExecute(command2); boolean hasException = true; try { command.run(); f2.get(); hasException = false; } catch (final Exception e) { throw ExceptionUtil.toRuntimeException(e, true); } finally { if (hasException && (!f2.isDone())) { // NOSONAR f2.cancel(false); } } } /** * Executes and complete the input commands in parallel. *
* if error happens in one task, {@code cancel} will be called for other unfinished tasks. * * @param command the first command to be executed in current thread. * @param command2 the second command to be executed in another thread. * @param command3 the third command to be executed in another thread. * @throws Exception if an error occurs during the execution of any command * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static void runInParallel(final Throwables.Runnable command, final Throwables.Runnable command2, final Throwables.Runnable command3) { final ContinuableFuture f2 = asyncExecute(command2); final ContinuableFuture f3 = asyncExecute(command3); boolean hasException = true; try { command.run(); f2.get(); f3.get(); hasException = false; } catch (final Exception e) { throw ExceptionUtil.toRuntimeException(e, true); } finally { if (hasException) { if (!f2.isDone()) { f2.cancel(false); } if (!f3.isDone()) { f3.cancel(false); } } } } /** * Executes and complete the input commands in parallel. *
* if error happens in one task, {@code cancel} will be called for other unfinished tasks. * * @param command the first command to be executed in current thread. * @param command2 the second command to be executed in another thread. * @param command3 the third command to be executed in another thread. * @param command4 the fourth command to be executed in another thread. * @throws Exception if an error occurs during the execution of any command * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static void runInParallel(final Throwables.Runnable command, final Throwables.Runnable command2, final Throwables.Runnable command3, final Throwables.Runnable command4) { final ContinuableFuture f2 = asyncExecute(command2); final ContinuableFuture f3 = asyncExecute(command3); final ContinuableFuture f4 = asyncExecute(command4); boolean hasException = true; try { command.run(); f2.get(); f3.get(); f4.get(); hasException = false; } catch (final Exception e) { throw ExceptionUtil.toRuntimeException(e, true); } finally { if (hasException) { if (!f2.isDone()) { f2.cancel(false); } if (!f3.isDone()) { f3.cancel(false); } if (!f4.isDone()) { f4.cancel(false); } } } } /** * Executes and complete the input commands in parallel. *
* if error happens in one task, {@code cancel} will be called for other unfinished tasks. * * @param command the first command to be executed in current thread. * @param command2 the second command to be executed in another thread. * @param command3 the third command to be executed in another thread. * @param command4 the fourth command to be executed in another thread. * @param command5 the fifth command to be executed in another thread. * @throws Exception if an error occurs during the execution of any command * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static void runInParallel(final Throwables.Runnable command, final Throwables.Runnable command2, final Throwables.Runnable command3, final Throwables.Runnable command4, final Throwables.Runnable command5) { final ContinuableFuture f2 = asyncExecute(command2); final ContinuableFuture f3 = asyncExecute(command3); final ContinuableFuture f4 = asyncExecute(command4); final ContinuableFuture f5 = asyncExecute(command5); boolean hasException = true; try { command.run(); f2.get(); f3.get(); f4.get(); f5.get(); hasException = false; } catch (final Exception e) { throw ExceptionUtil.toRuntimeException(e, true); } finally { if (hasException) { if (!f2.isDone()) { f2.cancel(false); } if (!f3.isDone()) { f3.cancel(false); } if (!f4.isDone()) { f4.cancel(false); } if (!f5.isDone()) { f5.cancel(false); } } } } /** * Executes the specified collection of commands/tasks in parallel. *
* If an error occurs in one task, {@code cancel} will be called for other unfinished tasks. * * @param commands the collection of commands/tasks to be executed asynchronously, except the first one which is executed in current thread. * @throws Exception if an error occurs during the execution of any command * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static void runInParallel(final Collection> commands) { runInParallel(commands, ASYNC_EXECUTOR.getExecutor()); } /** * Executes and complete the input commands in parallel. *
* if error happens in one task, {@code cancel} will be called for other unfinished tasks. * * @param commands the collection of commands/tasks to be executed asynchronously by the specified execute, except the first one which is executed in current thread. * @param executor the executor to use for processing * @throws Exception if an error occurs during the execution of any command * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static void runInParallel(final Collection> commands, final Executor executor) { if (isEmpty(commands)) { return; } final int cmdSize = commands.size(); final List> futures = new ArrayList<>(cmdSize - 1); boolean hasException = true; try { final Iterator> iter = commands.iterator(); final Throwables.Runnable firstCommand = iter.next(); while (iter.hasNext()) { futures.add(asyncExecute(iter.next(), executor)); } firstCommand.run(); for (final ContinuableFuture f : futures) { f.get(); } hasException = false; } catch (final Exception e) { throw ExceptionUtil.toRuntimeException(e, true); } finally { if (hasException) { for (final ContinuableFuture f : futures) { if (!f.isDone()) { f.cancel(false); } } } } } /** * Executes and completes the input commands in parallel. *
* If an error occurs in one task, {@code cancel()} will be called for other unfinished tasks. * * @param the returned type of the first command * @param the returned type of the second command * @param command the first command to be executed in current thread. * @param command2 the second command to be executed in another thread. * @return a tuple containing the results of the two commands * @throws Exception if an error occurs during the execution of any command * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static Tuple2 callInParallel(final Callable command, final Callable command2) { final ContinuableFuture f2 = asyncExecute(command2); boolean hasException = true; try { final R r = command.call(); final R2 r2 = f2.get(); hasException = false; return Tuple.of(r, r2); } catch (final Exception e) { throw ExceptionUtil.toRuntimeException(e, true); } finally { if (hasException && (!f2.isDone())) { // NOSONAR f2.cancel(false); } } } /** * Executes the specified commands in parallel and returns a tuple containing the results. *
* If an error occurs in one task, {@code cancel} will be called for other unfinished tasks. * * @param the type of the result of the first command * @param the type of the result of the second command * @param the type of the result of the third command * @param command the first command to be executed in current thread. * @param command2 the second command to be executed in another thread. * @param command3 the third command to be executed in another thread. * @return a tuple containing the results of the three commands * @throws Exception if an error occurs during the execution of any command * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static Tuple3 callInParallel(final Callable command, final Callable command2, final Callable command3) { final ContinuableFuture f2 = asyncExecute(command2); final ContinuableFuture f3 = asyncExecute(command3); boolean hasException = true; try { final R r = command.call(); final R2 r2 = f2.get(); final R3 r3 = f3.get(); hasException = false; return Tuple.of(r, r2, r3); } catch (final Exception e) { throw ExceptionUtil.toRuntimeException(e, true); } finally { if (hasException) { if (!f2.isDone()) { f2.cancel(false); } if (!f3.isDone()) { f3.cancel(false); } } } } /** * Executes the specified commands in parallel and returns a tuple containing the results. *
* If an error occurs in one task, {@code cancel} will be called for other unfinished tasks. * * @param the type of the result of the first command * @param the type of the result of the second command * @param the type of the result of the third command * @param the type of the result of the fourth command * @param command the first command to be executed in current thread. * @param command2 the second command to be executed in another thread. * @param command3 the third command to be executed in another thread. * @param command4 the fourth command to be executed in another thread. * @return a tuple containing the results of the four commands * @throws Exception if an error occurs during the execution of any command * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static Tuple4 callInParallel(final Callable command, final Callable command2, final Callable command3, final Callable command4) { final ContinuableFuture f2 = asyncExecute(command2); final ContinuableFuture f3 = asyncExecute(command3); final ContinuableFuture f4 = asyncExecute(command4); boolean hasException = true; try { final R r = command.call(); final R2 r2 = f2.get(); final R3 r3 = f3.get(); final R4 r4 = f4.get(); hasException = false; return Tuple.of(r, r2, r3, r4); } catch (final Exception e) { throw ExceptionUtil.toRuntimeException(e, true); } finally { if (hasException) { if (!f2.isDone()) { f2.cancel(false); } if (!f3.isDone()) { f3.cancel(false); } if (!f4.isDone()) { f4.cancel(false); } } } } /** * Executes the specified commands in parallel and returns a tuple containing the results. *
* If an error occurs in one task, {@code cancel} will be called for other unfinished tasks. * * @param the type of the result of the first command * @param the type of the result of the second command * @param the type of the result of the third command * @param the type of the result of the fourth command * @param the type of the result of the fifth command * @param command the first command to be executed in current thread. * @param command2 the second command to be executed in another thread. * @param command3 the third command to be executed in another thread. * @param command4 the fourth command to be executed in another thread. * @param command5 the fifth command to be executed in another thread. * @return a tuple containing the results of the five commands * @throws Exception if an error occurs during the execution of any command * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static Tuple5 callInParallel(final Callable command, final Callable command2, final Callable command3, final Callable command4, final Callable command5) { final ContinuableFuture f2 = asyncExecute(command2); final ContinuableFuture f3 = asyncExecute(command3); final ContinuableFuture f4 = asyncExecute(command4); final ContinuableFuture f5 = asyncExecute(command5); boolean hasException = true; try { final R r = command.call(); final R2 r2 = f2.get(); final R3 r3 = f3.get(); final R4 r4 = f4.get(); final R5 r5 = f5.get(); hasException = false; return Tuple.of(r, r2, r3, r4, r5); } catch (final Exception e) { throw ExceptionUtil.toRuntimeException(e, true); } finally { if (hasException) { if (!f2.isDone()) { f2.cancel(false); } if (!f3.isDone()) { f3.cancel(false); } if (!f4.isDone()) { f4.cancel(false); } if (!f5.isDone()) { f5.cancel(false); } } } } /** * Executes the specified collection of commands/tasks in parallel. *
* If an error occurs in one task, {@code cancel} will be called for other unfinished tasks. * * @param commands the collection of commands/tasks to be executed asynchronously, except the first one which is executed in current thread. * @return a list containing the results of all commands * @throws Exception if an error occurs during the execution of any command * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static List callInParallel(final Collection> commands) { return callInParallel(commands, ASYNC_EXECUTOR.getExecutor()); } /** * Executes the specified collection of commands/tasks in parallel. *
* If an error occurs in one task, {@code cancel} will be called for other unfinished tasks. * * @param commands the collection of commands/tasks to be executed asynchronously by the specified executor, except the first one which is executed in current thread. * @param executor the executor to use for processing * @return a list containing the results of all commands * @throws Exception if an error occurs during the execution of any command * @see Fn#r(com.landawn.abacus.util.function.Runnable) * @see Fn#c(com.landawn.abacus.util.function.Callable) * @see Fnn#r(Throwables.Runnable) * @see Fnn#c(Throwables.Callable) * @see Fnn#jr2r(Runnable) * @see Fnn#jc2c(Callable) */ public static List callInParallel(final Collection> commands, final Executor executor) throws IllegalArgumentException { if (isEmpty(commands)) { return new ArrayList<>(); } final int cmdSize = commands.size(); final List> futures = new ArrayList<>(cmdSize - 1); boolean hasException = true; try { final Iterator> iter = commands.iterator(); final Callable firstCommand = iter.next(); while (iter.hasNext()) { futures.add(asyncExecute(iter.next(), executor)); } final List result = new ArrayList<>(cmdSize); result.add(firstCommand.call()); for (final ContinuableFuture f : futures) { result.add(f.get()); } hasException = false; return result; } catch (final Exception e) { throw ExceptionUtil.toRuntimeException(e, true); } finally { if (hasException) { for (final ContinuableFuture f : futures) { if (!f.isDone()) { f.cancel(false); } } } } } /** * Executes the given action on batches of elements from the provided array. *
* The {@code batchAction} must not update or cache the input batch elements. * * @param The type of the elements in the array. * @param The type of the exception that the action may throw. * @param a The array whose elements are to be processed. * @param batchSize The size of the batches to be processed at a time. * @param batchAction The action to be executed on each batch of elements. The {@code batchAction} must not update or cache the input batch elements. * @throws IllegalArgumentException if the batchSize is not positive. * @throws E if the batchAction throws an exception. */ public static void runByBatch(final T[] a, final int batchSize, final Throwables.Consumer, E> batchAction) throws IllegalArgumentException, E { if (isEmpty(a)) { return; } runByBatch(Arrays.asList(a), batchSize, batchAction); } /** * Executes the given action on batches of elements from the provided iterable. *
* The {@code batchAction} must not update or cache the input batch elements. * * @param The type of the elements in the iterable. * @param The type of the exception that the action may throw. * @param iter The iterable whose elements are to be processed. * @param batchSize The size of the batches to be processed at a time. * @param batchAction The action to be executed on each batch of elements. The {@code batchAction} must not update or cache the input batch elements. * @throws IllegalArgumentException if the batchSize is not positive. * @throws E if the batchAction throws an exception. */ public static void runByBatch(final Iterable iter, final int batchSize, final Throwables.Consumer, E> batchAction) throws IllegalArgumentException, E { checkArgPositive(batchSize, cs.batchSize); if (iter == null) { return; } if (iter instanceof List) { final List list = (List) iter; final int totalSize = list.size(); if (totalSize <= batchSize) { batchAction.accept(list); } else { for (int i = 0; i < totalSize; i += batchSize) { batchAction.accept(list.subList(i, min(i + batchSize, totalSize))); } } } else { runByBatch(iter.iterator(), batchSize, batchAction); } } /** * Executes the given action on batches of elements from the provided iterator. *
* The {@code batchAction} must not update or cache the input batch elements. * * @param The type of the elements in the iterator. * @param The type of the exception that the action may throw. * @param iter The iterator whose elements are to be processed. * @param batchSize The size of the batches to be processed at a time. * @param batchAction The action to be executed on each batch of elements. The {@code batchAction} must not update or cache the input batch elements. * @throws IllegalArgumentException if the batchSize is not positive. * @throws E if the batchAction throws an exception. */ public static void runByBatch(final Iterator iter, final int batchSize, final Throwables.Consumer, E> batchAction) throws IllegalArgumentException, E { checkArgPositive(batchSize, cs.batchSize); if (iter == null || !iter.hasNext()) { return; } final T[] a = (T[]) new Object[batchSize]; int cnt = 0; while (iter.hasNext()) { a[cnt++ % batchSize] = iter.next(); if (cnt % batchSize == 0) { batchAction.accept(ImmutableList.of(a)); } } if (cnt % batchSize != 0) { batchAction.accept(ImmutableList.of(copyOfRange(a, 0, cnt % batchSize))); } } /** * Executes the given batch action after applying the specified element consumer on each batch element with index for preparing batch execution. * * @param The type of the elements in the array. * @param The type of the exception that the elementConsumer may throw. * @param The type of the exception that the batchAction may throw. * @param a The array whose elements are to be processed. * @param batchSize The size of the batches to be processed at a time. * @param elementConsumer The action to be applied to each element with index for preparing batch execution. * @param batchAction The action to be executed on each batch of elements. * @throws IllegalArgumentException if the batchSize is not positive. * @throws E if the elementConsumer throws an exception. * @throws E2 if the batchAction throws an exception. */ public static void runByBatch(final T[] a, final int batchSize, final Throwables.IntObjConsumer elementConsumer, final Throwables.Runnable batchAction) throws IllegalArgumentException, E, E2 { if (isEmpty(a)) { return; } runByBatch(Arrays.asList(a), batchSize, elementConsumer, batchAction); } /** * Executes the given batch action after applying the specified element consumer on each batch element with index for preparing batch execution. * * @param The type of the elements in the iterable. * @param The type of the exception that the elementConsumer may throw. * @param The type of the exception that the batchAction may throw. * @param iter The iterable whose elements are to be processed. * @param batchSize The size of the batches to be processed at a time. * @param elementConsumer The action to be applied to each element with index for preparing batch execution. * @param batchAction The action to be executed on each batch of elements. * @throws IllegalArgumentException if the batchSize is not positive. * @throws E if the elementConsumer throws an exception. * @throws E2 if the batchAction throws an exception. */ public static void runByBatch(final Iterable iter, final int batchSize, final Throwables.IntObjConsumer elementConsumer, final Throwables.Runnable batchAction) throws IllegalArgumentException, E, E2 { if (iter == null) { return; } runByBatch(iter.iterator(), batchSize, elementConsumer, batchAction); } /** * Executes the given batch action after applying the specified element consumer on each batch element with index for preparing batch execution. * * @param The type of the elements in the iterator. * @param The type of the exception that the elementConsumer may throw. * @param The type of the exception that the batchAction may throw. * @param iter The iterator whose elements are to be processed. * @param batchSize The size of the batches to be processed at a time. * @param elementConsumer The action to be applied to each element with index for preparing batch execution. * @param batchAction The action to be executed on each batch of elements. * @throws IllegalArgumentException if the batchSize is not positive. * @throws E if the elementConsumer throws an exception. * @throws E2 if the batchAction throws an exception. */ public static void runByBatch(final Iterator iter, final int batchSize, final Throwables.IntObjConsumer elementConsumer, final Throwables.Runnable batchAction) throws IllegalArgumentException, E, E2 { checkArgPositive(batchSize, cs.batchSize); if (iter == null || !iter.hasNext()) { return; } int cnt = 0; while (iter.hasNext()) { elementConsumer.accept(cnt, iter.next()); cnt++; if (cnt % batchSize == 0) { batchAction.run(); } } if (cnt % batchSize != 0) { batchAction.run(); } } /** * Executes the given function on batches of elements from the provided array. *
* The {@code batchAction} must not update or cache the input batch elements. * * @param The type of the elements in the array. * @param The type of the result returned by the batchAction function. * @param The type of the exception that the batchAction may throw. * @param a The array whose elements are to be processed. * @param batchSize The size of the batches to be processed at a time. * @param batchAction The action to be executed on each batch of elements. The {@code batchAction} must not update or cache the input batch elements. * @return A list of results returned by the batchAction function for each batch of elements. * @throws IllegalArgumentException if the batchSize is not positive. * @throws E if the batchAction throws an exception. */ public static List callByBatch(final T[] a, final int batchSize, final Throwables.Function, R, E> batchAction) throws IllegalArgumentException, E { if (isEmpty(a)) { return new ArrayList<>(); } return callByBatch(Arrays.asList(a), batchSize, batchAction); } /** * Executes the given function on batches of elements from the provided iterable. *
* The {@code batchAction} must not update or cache the input batch elements. * * @param The type of the elements in the iterable. * @param The type of the result returned by the batchAction function. * @param The type of the exception that the batchAction may throw. * @param iter The iterable whose elements are to be processed. * @param batchSize The size of the batches to be processed at a time. * @param batchAction The action to be executed on each batch of elements. The {@code batchAction} must not update or cache the input batch elements. * @return A list of results returned by the batchAction function for each batch of elements. * @throws IllegalArgumentException if the batchSize is not positive. * @throws E if the batchAction throws an exception. */ public static List callByBatch(final Iterable iter, final int batchSize, final Throwables.Function, R, E> batchAction) throws IllegalArgumentException, E { checkArgPositive(batchSize, cs.batchSize); if (iter == null) { return new ArrayList<>(); } if (iter instanceof List) { final List list = (List) iter; final int totalSize = list.size(); final List result = new ArrayList<>(totalSize % batchSize == 0 ? totalSize / batchSize : totalSize / batchSize + 1); if (totalSize <= batchSize) { result.add(batchAction.apply(list)); } else { for (int i = 0; i < totalSize; i += batchSize) { result.add(batchAction.apply(list.subList(i, min(i + batchSize, totalSize)))); } } return result; } else { return callByBatch(iter.iterator(), batchSize, batchAction); } } /** * Executes the given function on batches of elements from the provided iterator. *
* The {@code batchAction} must not update or cache the input batch elements. * * @param The type of the elements in the iterator. * @param The type of the result returned by the batchAction function. * @param The type of the exception that the batchAction may throw. * @param iter The iterator whose elements are to be processed. * @param batchSize The size of the batches to be processed at a time. * @param batchAction The action to be executed on each batch of elements. The {@code batchAction} must not update or cache the input batch elements. * @return A list of results returned by the batchAction function for each batch of elements. * @throws IllegalArgumentException if the batchSize is not positive. * @throws E if the batchAction throws an exception. */ public static List callByBatch(final Iterator iter, final int batchSize, final Throwables.Function, R, E> batchAction) throws IllegalArgumentException, E { checkArgPositive(batchSize, cs.batchSize); if (iter == null || !iter.hasNext()) { return new ArrayList<>(); } final T[] a = (T[]) new Object[batchSize]; final List result = new ArrayList<>(); int cnt = 0; while (iter.hasNext()) { a[cnt++ % batchSize] = iter.next(); if (cnt % batchSize == 0) { result.add(batchAction.apply(ImmutableList.of(a))); } } if (cnt % batchSize != 0) { result.add(batchAction.apply(ImmutableList.of(copyOfRange(a, 0, cnt % batchSize)))); } return result; } /** * Executes the given batch action after applying the specified element consumer on each batch element with index. * * @param The type of the elements in the array. * @param The type of the result returned by the batchAction function. * @param The type of the exception that the elementConsumer may throw. * @param The type of the exception that the batchAction may throw. * @param a The array whose elements are to be processed. * @param batchSize The size of the batches to be processed at a time. * @param elementConsumer The action to be applied to each element with index for preparing batch execution. * @param batchAction The action to be executed on each batch of elements. * @return A list of results returned by the batchAction function for each batch of elements. * @throws IllegalArgumentException if the batchSize is not positive. * @throws E if the elementConsumer throws an exception. * @throws E2 if the batchAction throws an exception. */ public static List callByBatch(final T[] a, final int batchSize, final Throwables.IntObjConsumer elementConsumer, final Throwables.Callable batchAction) throws IllegalArgumentException, E, E2 { if (isEmpty(a)) { return new ArrayList<>(); } return callByBatch(Arrays.asList(a), batchSize, elementConsumer, batchAction); } /** * Executes the given batch action after applying the specified element consumer on each batch element with index. * * @param The type of the elements in the iterable. * @param The type of the result returned by the batchAction function. * @param The type of the exception that the elementConsumer may throw. * @param The type of the exception that the batchAction may throw. * @param iter The iterable whose elements are to be processed. * @param batchSize The size of the batches to be processed at a time. * @param elementConsumer The action to be applied to each element with index for preparing batch execution. * @param batchAction The action to be executed on each batch of elements. * @throws IllegalArgumentException if the batchSize is not positive. * @throws E if the elementConsumer throws an exception. * @throws E2 if the batchAction throws an exception. */ public static List callByBatch(final Iterable iter, final int batchSize, final Throwables.IntObjConsumer elementConsumer, final Throwables.Callable batchAction) throws IllegalArgumentException, E, E2 { if (iter == null) { return new ArrayList<>(); } return callByBatch(iter.iterator(), batchSize, elementConsumer, batchAction); } /** * Executes the given batch action after applying the specified element consumer on each batch element with index. * * @param The type of the elements in the iterator. * @param The type of the result returned by the batchAction function. * @param The type of the exception that the elementConsumer may throw. * @param The type of the exception that the batchAction may throw. * @param iter The iterator whose elements are to be processed. * @param batchSize The size of the batches to be processed at a time. * @param elementConsumer The action to be applied to each element with index for preparing batch execution. * @param batchAction The action to be executed on each batch of elements. * @return A list of results returned by the batchAction function for each batch of elements. * @throws IllegalArgumentException if the batchSize is not positive. * @throws E if the elementConsumer throws an exception. * @throws E2 if the batchAction throws an exception. */ public static List callByBatch(final Iterator iter, final int batchSize, final Throwables.IntObjConsumer elementConsumer, final Throwables.Callable batchAction) throws IllegalArgumentException, E, E2 { checkArgPositive(batchSize, cs.batchSize); if (iter == null || !iter.hasNext()) { return new ArrayList<>(); } final List result = new ArrayList<>(); int cnt = 0; while (iter.hasNext()) { elementConsumer.accept(cnt++, iter.next()); if (cnt % batchSize == 0) { result.add(batchAction.call()); } } if (cnt % batchSize != 0) { result.add(batchAction.call()); } return result; } /** * Note: Copied from Google Guava under Apache License v2.0 *
*
* * If a thread is interrupted during such a call, the call continues to block until the result is available or the timeout elapses, and only then re-interrupts the thread. * * @param cmd * @throws IllegalArgumentException */ public static void runUninterruptibly(final Throwables.Runnable cmd) throws IllegalArgumentException { boolean interrupted = false; try { while (true) { try { cmd.run(); return; } catch (final InterruptedException e) { interrupted = true; } } } finally { if (interrupted) { Thread.currentThread().interrupt(); } } } /** * Note: Copied from Google Guava under Apache License v2.0 *
*
* * If a thread is interrupted during such a call, the call continues to block until the result is available or the * timeout elapses, and only then re-interrupts the thread. * @param cmd the command to execute with the remaining time in milliseconds * @param timeoutInMillis * * @throws IllegalArgumentException */ public static void runUninterruptibly(final Throwables.LongConsumer cmd, final long timeoutInMillis) throws IllegalArgumentException { boolean interrupted = false; try { long remainingMillis = timeoutInMillis; final long sysMillis = System.currentTimeMillis(); final long end = remainingMillis >= Long.MAX_VALUE - sysMillis ? Long.MAX_VALUE : sysMillis + remainingMillis; while (true) { try { cmd.accept(remainingMillis); return; } catch (final InterruptedException e) { interrupted = true; remainingMillis = end - System.currentTimeMillis(); } } } finally { if (interrupted) { Thread.currentThread().interrupt(); } } } /** * Note: Copied from Google Guava under Apache License v2.0 *
*
* * If a thread is interrupted during such a call, the call continues to block until the result is available or the * timeout elapses, and only then re-interrupts the thread. * @param cmd the command to execute with the remaining time and unit * @param timeout * @param unit * * @throws IllegalArgumentException if the specified {@code unit/cmd} is {@code null}. */ public static void runUninterruptibly(@NotNull final Throwables.BiConsumer cmd, final long timeout, @NotNull final TimeUnit unit) throws IllegalArgumentException { checkArgNotNull(unit, cs.unit); boolean interrupted = false; try { long remainingNanos = unit.toNanos(timeout); final long sysNanos = System.nanoTime(); final long end = remainingNanos >= Long.MAX_VALUE - sysNanos ? Long.MAX_VALUE : sysNanos + remainingNanos; while (true) { try { cmd.accept(remainingNanos, TimeUnit.NANOSECONDS); return; } catch (final InterruptedException e) { interrupted = true; remainingNanos = end - System.nanoTime(); } } } finally { if (interrupted) { Thread.currentThread().interrupt(); } } } /** * Note: Copied from Google Guava under Apache License v2.0 *
*
* * If a thread is interrupted during such a call, the call continues to block until the result is available or the * timeout elapses, and only then re-interrupts the thread. * * @param * @param cmd * @return * @throws IllegalArgumentException */ public static T callUninterruptibly(final Throwables.Callable cmd) throws IllegalArgumentException { boolean interrupted = false; try { while (true) { try { return cmd.call(); } catch (final InterruptedException e) { interrupted = true; } } } finally { if (interrupted) { Thread.currentThread().interrupt(); } } } /** * Note: Copied from Google Guava under Apache License v2.0 *
*
* * If a thread is interrupted during such a call, the call continues to block until the result is available or the * timeout elapses, and only then re-interrupts the thread. * @param cmd the command to execute with the remaining time in milliseconds * @param timeoutInMillis * * @param * @return * @throws IllegalArgumentException */ public static T callUninterruptibly(final Throwables.LongFunction cmd, final long timeoutInMillis) throws IllegalArgumentException { boolean interrupted = false; try { long remainingMillis = timeoutInMillis; final long sysMillis = System.currentTimeMillis(); final long end = remainingMillis >= Long.MAX_VALUE - sysMillis ? Long.MAX_VALUE : sysMillis + remainingMillis; while (true) { try { return cmd.apply(remainingMillis); } catch (final InterruptedException e) { interrupted = true; remainingMillis = end - System.currentTimeMillis(); } } } finally { if (interrupted) { Thread.currentThread().interrupt(); } } } /** * Note: Copied from Google Guava under Apache License v2.0 *
*
* * If a thread is interrupted during such a call, the call continues to block until the result is available or the * timeout elapses, and only then re-interrupts the thread. * @param cmd the command to execute with the remaining time and unit * @param timeout * @param unit * * @param * @return * @throws IllegalArgumentException if the specified {@code unit/cmd} is {@code null}. */ public static T callUninterruptibly(@NotNull final Throwables.BiFunction cmd, final long timeout, @NotNull final TimeUnit unit) throws IllegalArgumentException { checkArgNotNull(unit, cs.unit); boolean interrupted = false; try { long remainingNanos = unit.toNanos(timeout); final long sysNanos = System.nanoTime(); final long end = remainingNanos >= Long.MAX_VALUE - sysNanos ? Long.MAX_VALUE : sysNanos + remainingNanos; while (true) { try { return cmd.apply(remainingNanos, TimeUnit.NANOSECONDS); } catch (final InterruptedException e) { interrupted = true; remainingNanos = end - System.nanoTime(); } } } finally { if (interrupted) { Thread.currentThread().interrupt(); } } } /** * Pauses the execution of the current thread for a specified time. * * @param timeoutInMillis The time, in milliseconds, to pause the thread. */ public static void sleep(final long timeoutInMillis) { if (timeoutInMillis <= 0) { return; } try { TimeUnit.MILLISECONDS.sleep(timeoutInMillis); } catch (final InterruptedException e) { throw ExceptionUtil.toRuntimeException(e, true); } } /** * Pauses the execution of the current thread for a specified time. * * @param timeout The time to pause the thread. The unit of time is determined by the unit parameter. * @param unit The unit of time for the timeout parameter. This should be a valid TimeUnit enumeration value. * @throws IllegalArgumentException if the specified {@code unit} is {@code null}. */ public static void sleep(final long timeout, @NotNull final TimeUnit unit) throws IllegalArgumentException { checkArgNotNull(unit, cs.unit); if (timeout <= 0) { return; } try { unit.sleep(timeout); } catch (final InterruptedException e) { throw ExceptionUtil.toRuntimeException(e, true); } } /** * Note: Copied from Google Guava under Apache License v2.0 *
*
* * If a thread is interrupted during such a call, the call continues to block until the result is available or the * timeout elapses, and only then re-interrupts the thread. * * @param timeoutInMillis */ public static void sleepUninterruptibly(final long timeoutInMillis) { if (timeoutInMillis <= 0) { return; } boolean interrupted = false; try { long remainingNanos = TimeUnit.MILLISECONDS.toNanos(timeoutInMillis); final long sysNanos = System.nanoTime(); final long end = remainingNanos >= Long.MAX_VALUE - sysNanos ? Long.MAX_VALUE : sysNanos + remainingNanos; while (true) { try { // TimeUnit.sleep() treats negative timeouts just like zero. TimeUnit.NANOSECONDS.sleep(remainingNanos); return; } catch (final InterruptedException e) { interrupted = true; remainingNanos = end - System.nanoTime(); } } } finally { if (interrupted) { Thread.currentThread().interrupt(); } } } /** * Note: Copied from Google Guava under Apache License v2.0 *
*
* * If a thread is interrupted during such a call, the call continues to block until the result is available or the * timeout elapses, and only then re-interrupts the thread. * * @param timeout * @param unit * @throws IllegalArgumentException if the specified {@code unit} is {@code null}. */ public static void sleepUninterruptibly(final long timeout, @NotNull final TimeUnit unit) throws IllegalArgumentException { checkArgNotNull(unit, cs.unit); if (timeout <= 0) { return; } boolean interrupted = false; try { long remainingNanos = unit.toNanos(timeout); final long sysNanos = System.nanoTime(); final long end = remainingNanos >= Long.MAX_VALUE - sysNanos ? Long.MAX_VALUE : sysNanos + remainingNanos; while (true) { try { // TimeUnit.sleep() treats negative timeouts just like zero. TimeUnit.NANOSECONDS.sleep(remainingNanos); return; } catch (final InterruptedException e) { interrupted = true; remainingNanos = end - System.nanoTime(); } } } finally { if (interrupted) { Thread.currentThread().interrupt(); } } } // /** // * // * @param e // * @param type // * @return // * @see ExceptionUtil#hasCause(Throwable, Class) // */ // @Beta // public static boolean hasCause(final Throwable e, final Class type) { // return ExceptionUtil.hasCause(e, type); // } // // /** // * Returns the specified {@code Throwable e} if there is no cause found in it ({@code e.getCause() == null}). // * // * @param e // * @return // * @see ExceptionUtil#firstCause(Throwable) // */ // @Beta // public static Throwable firstCause(final Throwable e) { // return ExceptionUtil.firstCause(e); // } /** * Executes the given {@code Callable} and returns a {@code Nullable} containing the result. * If an exception occurs during the execution, an empty {@code Nullable} is returned. * * @param the type of the result * @param cmd the {@code Callable} to be executed * @return a {@code Nullable} containing the result or an empty {@code Nullable} if an exception occurs * @see Try#call(Throwables.Function) * @see Try#call(Throwables.Function, Object) * @see Try#call(Throwables.Function, Supplier) */ @Beta public static Nullable tryOrEmptyIfExceptionOccurred(final Callable cmd) { try { return Nullable.of(cmd.call()); } catch (final Exception e) { return Nullable.empty(); } } /** * Executes the given function with the provided initial value and returns a {@code Nullable} containing the result. * If an exception occurs during the execution, an empty {@code Nullable} is returned. * * @param the type of the initial value * @param the type of the result * @param init the initial value to be passed to the function * @param func the function to be executed * @return a {@code Nullable} containing the result or an empty {@code Nullable} if an exception occurs * @see Try#call(Throwables.Function) * @see Try#call(Throwables.Function, Object) * @see Try#call(Throwables.Function, Supplier) */ @Beta public static Nullable tryOrEmptyIfExceptionOccurred(final T init, final Throwables.Function func) { try { return Nullable.of(func.apply(init)); } catch (final Exception e) { return Nullable.empty(); } } /** * Executes the given {@code Callable} and returns the result. * If an exception occurs during the execution, the provided default value is returned. * * @param the type of the result * @param cmd the {@code Callable} to be executed * @param defaultIfExceptionOccurred the default value to return if an exception occurs * @return the result of the {@code Callable} or the default value if an exception occurs * @see Try#call(Throwables.Function) * @see Try#call(Throwables.Function, Object) * @see Try#call(Throwables.Function, Supplier) */ @Beta public static R tryOrDefaultIfExceptionOccurred(final Callable cmd, final R defaultIfExceptionOccurred) { try { return cmd.call(); } catch (final Exception e) { return defaultIfExceptionOccurred; } } /** * Executes the given function with the provided initial value and returns the result. * If an exception occurs during the execution, the provided default value is returned. * * @param the type of the initial value * @param the type of the result * @param init the initial value to be passed to the function * @param func the function to be executed * @param defaultIfExceptionOccurred the default value to return if an exception occurs * @return the result of the function or the default value if an exception occurs * @see Try#call(Throwables.Function) * @see Try#call(Throwables.Function, Object) * @see Try#call(Throwables.Function, Supplier) */ @Beta public static R tryOrDefaultIfExceptionOccurred(final T init, final Throwables.Function func, final R defaultIfExceptionOccurred) { try { return func.apply(init); } catch (final Exception e) { return defaultIfExceptionOccurred; } } /** * Executes the given {@code Callable} and returns the result. * If an exception occurs during the execution, the result from the provided supplier is returned. * * @param the type of the result * @param cmd the {@code Callable} to be executed * @param supplierForDefaultIfExceptionOccurred the supplier to provide the default value if an exception occurs * @return the result of the {@code Callable} or the result from the supplier if an exception occurs * @see Try#call(Throwables.Function) * @see Try#call(Throwables.Function, Object) * @see Try#call(Throwables.Function, Supplier) */ @Beta public static R tryOrDefaultIfExceptionOccurred(final Callable cmd, final Supplier supplierForDefaultIfExceptionOccurred) { try { return cmd.call(); } catch (final Exception e) { return supplierForDefaultIfExceptionOccurred.get(); } } /** * Executes the given function with the provided initial value and returns the result. * If an exception occurs during the execution, the result from the provided supplier is returned. * * @param the type of the initial value * @param the type of the result * @param init the initial value to be passed to the function * @param func the function to be executed * @param supplierForDefaultIfExceptionOccurred the supplier to provide the default value if an exception occurs * @return the result of the function or the result from the supplier if an exception occurs * @see Try#call(Throwables.Function) * @see Try#call(Throwables.Function, Object) * @see Try#call(Throwables.Function, Supplier) */ @Beta public static R tryOrDefaultIfExceptionOccurred(final T init, final Throwables.Function func, final Supplier supplierForDefaultIfExceptionOccurred) { try { return func.apply(init); } catch (final Exception e) { return supplierForDefaultIfExceptionOccurred.get(); } } /** * Returns a {@code Nullable} containing the result of the given supplier if the condition is {@code true}. * If the condition is {@code false}, returns an empty {@code Nullable}. * * @param the type of the result * @param the type of the exception that the supplier may throw * @param b the condition to evaluate * @param supplier the supplier to provide the result if the condition is true * @return a {@code Nullable} containing the result of the supplier if the condition is {@code true}, otherwise an empty Nullable * @throws E if the supplier throws an exception */ @Beta public static Nullable ifOrEmpty(final boolean b, final Throwables.Supplier supplier) throws E { if (b) { return Nullable.of(supplier.get()); } else { return Nullable.empty(); } } // Maybe misused: N.ifOrElse(user != null, user.getFirstName(), firstName -> N.println(firstName)); // /** // * Returns a {@code Nullable} with value returned by {@code func.apply(init)} if b is {@code true}, // * otherwise returns an empty {@code Nullable} if b is false. // * // * @param // * @param // * @param // * @param b // * @param init // * @param func // * @return // * @throws E the e // */ // @Beta // public static Nullable ifOrEmpty(final boolean b, final T init, final Throwables.Function func) // throws E { // if (b) { // return Nullable.of(func.apply(init)); // } else { // return Nullable.empty(); // } // } // // /** // * Returns a {@code Nullable} with value returned by {@code func.apply(initSupplier.get())} if b is {@code true}, // * otherwise returns an empty {@code Nullable} if b is false. // * // * @param // * @param // * @param // * @param b // * @param initSupplier // * @param func // * @return // * @throws E the e // */ // @Beta // public static Nullable ifOrEmpty(final boolean b, final Supplier initSupplier, // final Throwables.Function func) throws E { // if (b) { // return Nullable.of(func.apply(initSupplier.get())); // } else { // return Nullable.empty(); // } // } // Maybe misused: N.ifOrElse(user != null, user.getFirstName(), firstName -> N.println(firstName)); // /** // * Executes the provided actions based on the boolean condition. // * // * @param The type of the initial object to be consumed by the actions. // * @param The type of exception that the first action may throw. // * @param The type of exception that the second action may throw. // * @param b The boolean condition to test. // * @param init The initial object to be consumed by the actions. // * @param actionForTrue The action to be executed if the condition is true. // * @param actionForFalse The action to be executed if the condition is false. // * @throws E1 if the condition is true and the execution of actionForTrue throws this exception. // * @throws E2 if the condition is false and the execution of actionForFalse throws this exception. // */ // @Beta // public static void ifOrElse(final boolean b, final T init, // final Throwables.Consumer actionForTrue, final Throwables.Consumer actionForFalse) throws E1, E2 { // if (b) { // if (actionForTrue != null) { // actionForTrue.accept(init); // } // } else { // if (actionForFalse != null) { // actionForFalse.accept(init); // } // } // } // // /** // * Executes the provided actions based on the boolean condition. // * // * @param The type of the initial object to be consumed by the actions. // * @param The type of exception that the first action may throw. // * @param The type of exception that the second action may throw. // * @param b The boolean condition to test. // * @param initSupplier The supplier of initial object to be consumed by the actions. // * @param actionForTrue The action to be executed if the condition is true. // * @param actionForFalse The action to be executed if the condition is false. // * @throws E1 if the condition is true and the execution of actionForTrue throws this exception. // * @throws E2 if the condition is false and the execution of actionForFalse throws this exception. // */ // @Beta // public static void ifOrElse(final boolean b, final Supplier initSupplier, // final Throwables.Consumer actionForTrue, final Throwables.Consumer actionForFalse) throws E1, E2 { // if (b) { // if (actionForTrue != null) { // actionForTrue.accept(initSupplier.get()); // } // } else { // if (actionForFalse != null) { // actionForFalse.accept(initSupplier.get()); // } // } // } // Maybe misused: N.ifOrElse(user != null, user.getFirstName(), firstName -> N.println(firstName)); // /** // * Returns a {@code Nullable} with value returned by {@code func.apply(init)} if b is {@code true}, // * otherwise returns an empty {@code Nullable} if b is false. // * // * @param // * @param // * @param // * @param b // * @param init // * @param func // * @return // * @throws E the e // */ // @Beta // public static Nullable ifOrEmpty(final boolean b, final T init, final Throwables.Function func) // throws E { // if (b) { // return Nullable.of(func.apply(init)); // } else { // return Nullable.empty(); // } // } // // /** // * Returns a {@code Nullable} with value returned by {@code func.apply(initSupplier.get())} if b is {@code true}, // * otherwise returns an empty {@code Nullable} if b is false. // * // * @param // * @param // * @param // * @param b // * @param initSupplier // * @param func // * @return // * @throws E the e // */ // @Beta // public static Nullable ifOrEmpty(final boolean b, final Supplier initSupplier, // final Throwables.Function func) throws E { // if (b) { // return Nullable.of(func.apply(initSupplier.get())); // } else { // return Nullable.empty(); // } // } /** * Executes the provided actions based on the boolean condition. * * @param The type of exception that the first action may throw. * @param The type of exception that the second action may throw. * @param b The boolean condition to test. * @param actionForTrue The action to be executed if the condition is {@code true}. * @param actionForFalse The action to be executed if the condition is {@code false}. * @throws E1 if the condition is {@code true} and the execution of actionForTrue throws this exception. * @throws E2 if the condition is {@code false} and the execution of actionForFalse throws this exception. * @deprecated it's not a good idea? if-else is better? */ @Deprecated public static void ifOrElse(final boolean b, final Throwables.Runnable actionForTrue, final Throwables.Runnable actionForFalse) throws E1, E2 { if (b) { if (actionForTrue != null) { actionForTrue.run(); } } else { if (actionForFalse != null) { actionForFalse.run(); } } } /** * Executes the given {@code Consumer} if the provided object is not {@code null}. * * @param the type of the object * @param the type of the exception that the consumer may throw * @param obj the object to be checked for null * @param cmd the {@code Consumer} to be executed if the object is not null * @throws E if the consumer throws an exception */ @Beta public static void ifNotNull(final T obj, final Throwables.Consumer cmd) throws E { if (obj != null) { cmd.accept(obj); } } /** * Executes the provided action if the given {@code CharSequence} is not empty. * * @param The type of the {@code CharSequence}. * @param The type of exception that the action may throw. * @param c The {@code CharSequence} to be tested for emptiness. * @param cmd The action to be executed if the {@code CharSequence} is not empty. * @throws E if the execution of the action throws this exception. */ @Beta public static void ifNotEmpty(final CS c, final Throwables.Consumer cmd) throws E { if (notEmpty(c)) { cmd.accept(c); } } /** * Executes the provided action if the given collection is not empty. * * @param The type of the collection. * @param The type of exception that the action may throw. * @param c The collection to be tested for emptiness. * @param cmd The action to be executed if the collection is not empty. * @throws E if the execution of the action throws this exception. */ @SuppressWarnings("rawtypes") @Beta public static void ifNotEmpty(final C c, final Throwables.Consumer cmd) throws E { if (notEmpty(c)) { cmd.accept(c); } } /** * Executes the provided action if the given map is not empty. * * @param The type of the map. * @param The type of exception that the action may throw. * @param m The map to be tested for emptiness. * @param cmd The action to be executed if the map is not empty. * @throws E if the execution of the action throws this exception. */ @SuppressWarnings("rawtypes") @Beta public static void ifNotEmpty(final M m, final Throwables.Consumer cmd) throws E { if (notEmpty(m)) { cmd.accept(m); } } // Maybe misused: N.ifOrElse(user != null, user.getFirstName(), firstName -> N.println(firstName)); // /** // * Returns a {@code Nullable} with value returned by {@code func.apply(init)} if b is {@code true}, // * otherwise returns an empty {@code Nullable} if b is false. // * // * @param // * @param // * @param // * @param b // * @param init // * @param func // * @return // * @throws E the e // */ // @Beta // public static Nullable ifOrEmpty(final boolean b, final T init, final Throwables.Function func) // throws E { // if (b) { // return Nullable.of(func.apply(init)); // } else { // return Nullable.empty(); // } // } // // /** // * Returns a {@code Nullable} with value returned by {@code func.apply(initSupplier.get())} if b is {@code true}, // * otherwise returns an empty {@code Nullable} if b is false. // * // * @param // * @param // * @param // * @param b // * @param initSupplier // * @param func // * @return // * @throws E the e // */ // @Beta // public static Nullable ifOrEmpty(final boolean b, final Supplier initSupplier, // final Throwables.Function func) throws E { // if (b) { // return Nullable.of(func.apply(initSupplier.get())); // } else { // return Nullable.empty(); // } // } /** * Creates a lazy-initialized supplier from the provided supplier. * The supplier's get() method will not be called until necessary and only be called only because the returned value will be cached. * * @param The type of results supplied by this supplier * @param supplier The supplier to be lazily initialized * @return A lazy-initialized supplier */ @Beta public static com.landawn.abacus.util.function.Supplier lazyInit(final Supplier supplier) { return LazyInitializer.of(supplier); } /** * Creates a lazy-initialized supplier from the provided supplier. * The supplier's get() method will not be called until necessary and only be called only because the returned value will be cached. * * @param The type of results supplied by this supplier * @param supplier The supplier to be lazily initialized * @return A lazy-initialized supplier */ @Beta public static Throwables.Supplier lazyInitialize(final Throwables.Supplier supplier) { return Throwables.LazyInitializer.of(supplier); } static Iterator getDescendingIteratorIfPossible(final Iterable c) { if (c instanceof Deque) { return ((Deque) c).descendingIterator(); } else { try { Method m = null; if ((m = ClassUtil.getDeclaredMethod(c.getClass(), "descendingIterator")) != null && Modifier.isPublic(m.getModifiers()) && Iterator.class.isAssignableFrom(m.getReturnType())) { return ClassUtil.invokeMethod(c, m); } } catch (final Exception e) { // continue } } return null; // NOSONAR } /** * Converts the provided exception to a runtime exception. * * @param e The exception to be converted to a runtime exception. * @return A RuntimeException that represents the provided exception. * @see ExceptionUtil#toRuntimeException(Exception) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) */ @Beta public static RuntimeException toRuntimeException(final Exception e) { return ExceptionUtil.toRuntimeException(e); } /** * Converts the specified {@code Throwable} to a {@code RuntimeException} if it's a checked {@code exception} or an {@code Error}, otherwise returns itself. * * @param e The throwable to be converted to a runtime exception. * @return A RuntimeException that represents the provided throwable. * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) */ @Beta public static RuntimeException toRuntimeException(final Throwable e) { return ExceptionUtil.toRuntimeException(e); } // /** // * Converts the specified {@code Throwable} to a {@code RuntimeException} if it's a checked exception, // * or throws it if it's an {@code Error}, based on the provided flag. // * // * @param e the throwable to be converted to a runtime exception or thrown if it's an error // * @param throwIfItIsError a flag indicating whether to throw the throwable if it's an error // * @return a RuntimeException that represents the provided throwable // * @throws Error if the throwable is an error and the flag is set to true // * @see ExceptionUtil#toRuntimeException(Throwable, boolean) // * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) // */ // @Beta // public static RuntimeException toRuntimeException(final Throwable e, final boolean throwIfItIsError) { // return ExceptionUtil.toRuntimeException(e, true, throwIfItIsError); // } // /** // * // * @param e // * @param type // * @return // * @see ExceptionUtil#hasCause(Throwable, Class) // */ // @Beta // public static boolean hasCause(final Throwable e, final Class type) { // return ExceptionUtil.hasCause(e, type); // } // // /** // * Returns the specified {@code Throwable e} if there is no cause found in it ({@code e.getCause() == null}). // * // * @param e // * @return // * @see ExceptionUtil#firstCause(Throwable) // */ // @Beta // public static Throwable firstCause(final Throwable e) { // return ExceptionUtil.firstCause(e); // } /** * Prints the given object's string representation to the standard output stream (System.out) and returns the object. * The object's string representation is obtained by calling {@code N.toString(Object)} method. * * @param The type of the object to be printed. * @param obj The object to be printed. * @return The same object that was printed. */ @SuppressWarnings("rawtypes") public static T println(final T obj) { if (obj instanceof Collection) { //noinspection resource System.out.println(Joiner.with(Strings.ELEMENT_SEPARATOR, "[", "]").reuseCachedBuffer().appendAll((Collection) obj).toString()); //NOSONAR } else if (obj instanceof Object[]) { //noinspection resource System.out.println(Joiner.with(Strings.ELEMENT_SEPARATOR, "[", "]").reuseCachedBuffer().appendAll((Object[]) obj).toString()); //NOSONAR } else if (obj instanceof Map) { //noinspection resource System.out.println(Joiner.with(Strings.ELEMENT_SEPARATOR, "=", "{", "}").reuseCachedBuffer().appendEntries((Map) obj).toString()); //NOSONAR } else { System.out.println(toString(obj)); //NOSONAR } return obj; } // public static void printlnForEach(final Object[] a) { // if (a == null) { // println("null"); // } else if (a.length == 0) { // println("[]"); // } else { // for (Object e : a) { // println(e); // } // } // } // // public static void printlnForEach(final Iterable iter) { // if (iter == null) { // println("null"); // } else { // printlnForEach(iter.iterator()); // } // } // // public static void printlnForEach(final Iterator iter) { // if (iter == null) { // println("null"); // } else if (!iter.hasNext()) { // println("[]"); // } else { // while (iter.hasNext()) { // println(iter.next()); // } // } // } /** * Prints the formatted string to the standard output using the specified format and arguments. * * @param format the format string * @param args the arguments referenced by the format specifiers in the format string * @see String#format(String, Object...) * @see #println(Object) */ @SafeVarargs public static void fprintln(final String format, final Object... args) { System.out.printf(format, args); //NOSONAR System.out.println(); //NOSONAR } }