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

org.apache.commons.collections4.CollectionUtils Maven / Gradle / Ivy

Go to download

The Apache Commons Collections package contains types that extend and augment the Java Collections Framework.

There is a newer version: 4.5.0-M1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.commons.collections4;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections4.bag.HashBag;
import org.apache.commons.collections4.collection.PredicatedCollection;
import org.apache.commons.collections4.collection.SynchronizedCollection;
import org.apache.commons.collections4.collection.TransformedCollection;
import org.apache.commons.collections4.collection.UnmodifiableBoundedCollection;
import org.apache.commons.collections4.collection.UnmodifiableCollection;
import org.apache.commons.collections4.functors.TruePredicate;
import org.apache.commons.collections4.iterators.CollatingIterator;
import org.apache.commons.collections4.iterators.PermutationIterator;

/**
 * Provides utility methods and decorators for {@link Collection} instances.
 * 

* Various utility methods might put the input objects into a Set/Map/Bag. In case * the input objects override {@link Object#equals(Object)}, it is mandatory that * the general contract of the {@link Object#hashCode()} method is maintained. *

* NOTE: From 4.0, method parameters will take {@link Iterable} objects when possible. * * @since 1.0 */ public class CollectionUtils { /** * Helper class to easily access cardinality properties of two collections. * @param the element type */ private static class CardinalityHelper { /** Contains the cardinality for each object in collection A. */ final Map cardinalityA; /** Contains the cardinality for each object in collection B. */ final Map cardinalityB; /** * Create a new CardinalityHelper for two collections. * @param a the first collection * @param b the second collection */ public CardinalityHelper(final Iterable a, final Iterable b) { cardinalityA = CollectionUtils.getCardinalityMap(a); cardinalityB = CollectionUtils.getCardinalityMap(b); } /** * Returns the maximum frequency of an object. * @param obj the object * @return the maximum frequency of the object */ public final int max(final Object obj) { return Math.max(freqA(obj), freqB(obj)); } /** * Returns the minimum frequency of an object. * @param obj the object * @return the minimum frequency of the object */ public final int min(final Object obj) { return Math.min(freqA(obj), freqB(obj)); } /** * Returns the frequency of this object in collection A. * @param obj the object * @return the frequency of the object in collection A */ public int freqA(final Object obj) { return getFreq(obj, cardinalityA); } /** * Returns the frequency of this object in collection B. * @param obj the object * @return the frequency of the object in collection B */ public int freqB(final Object obj) { return getFreq(obj, cardinalityB); } private int getFreq(final Object obj, final Map freqMap) { final Integer count = freqMap.get(obj); if (count != null) { return count.intValue(); } return 0; } } /** * Helper class for set-related operations, e.g. union, subtract, intersection. * @param the element type */ private static class SetOperationCardinalityHelper extends CardinalityHelper implements Iterable { /** Contains the unique elements of the two collections. */ private final Set elements; /** Output collection. */ private final List newList; /** * Create a new set operation helper from the two collections. * @param a the first collection * @param b the second collection */ public SetOperationCardinalityHelper(final Iterable a, final Iterable b) { super(a, b); elements = new HashSet<>(); addAll(elements, a); addAll(elements, b); // the resulting list must contain at least each unique element, but may grow newList = new ArrayList<>(elements.size()); } @Override public Iterator iterator() { return elements.iterator(); } /** * Add the object {@code count} times to the result collection. * @param obj the object to add * @param count the count */ public void setCardinality(final O obj, final int count) { for (int i = 0; i < count; i++) { newList.add(obj); } } /** * Returns the resulting collection. * @return the result */ public Collection list() { return newList; } } /** * An empty unmodifiable collection. * The JDK provides empty Set and List implementations which could be used for * this purpose. However they could be cast to Set or List which might be * undesirable. This implementation only implements Collection. */ @SuppressWarnings("rawtypes") // we deliberately use the raw type here public static final Collection EMPTY_COLLECTION = Collections.emptyList(); /** * CollectionUtils should not normally be instantiated. */ private CollectionUtils() {} /** * Returns the immutable EMPTY_COLLECTION with generic type safety. * * @see #EMPTY_COLLECTION * @since 4.0 * @param the element type * @return immutable empty collection */ @SuppressWarnings("unchecked") // OK, empty collection is compatible with any type public static Collection emptyCollection() { return EMPTY_COLLECTION; } /** * Returns an immutable empty collection if the argument is null, * or the argument itself otherwise. * * @param the element type * @param collection the collection, possibly null * @return an empty collection if the argument is null */ public static Collection emptyIfNull(final Collection collection) { return collection == null ? CollectionUtils.emptyCollection() : collection; } /** * Returns a {@link Collection} containing the union of the given * {@link Iterable}s. *

* The cardinality of each element in the returned {@link Collection} will * be equal to the maximum of the cardinality of that element in the two * given {@link Iterable}s. * * @param a the first collection, must not be null * @param b the second collection, must not be null * @param the generic type that is able to represent the types contained * in both input collections. * @return the union of the two collections * @see Collection#addAll */ public static Collection union(final Iterable a, final Iterable b) { final SetOperationCardinalityHelper helper = new SetOperationCardinalityHelper<>(a, b); for (final O obj : helper) { helper.setCardinality(obj, helper.max(obj)); } return helper.list(); } /** * Returns a {@link Collection} containing the intersection of the given * {@link Iterable}s. *

* The cardinality of each element in the returned {@link Collection} will * be equal to the minimum of the cardinality of that element in the two * given {@link Iterable}s. * * @param a the first collection, must not be null * @param b the second collection, must not be null * @param the generic type that is able to represent the types contained * in both input collections. * @return the intersection of the two collections * @see Collection#retainAll * @see #containsAny */ public static Collection intersection(final Iterable a, final Iterable b) { final SetOperationCardinalityHelper helper = new SetOperationCardinalityHelper<>(a, b); for (final O obj : helper) { helper.setCardinality(obj, helper.min(obj)); } return helper.list(); } /** * Returns a {@link Collection} containing the exclusive disjunction * (symmetric difference) of the given {@link Iterable}s. *

* The cardinality of each element e in the returned * {@link Collection} will be equal to * max(cardinality(e,a),cardinality(e,b)) - min(cardinality(e,a), * cardinality(e,b)). *

* This is equivalent to * {@code {@link #subtract subtract}({@link #union union(a,b)},{@link #intersection intersection(a,b)})} * or * {@code {@link #union union}({@link #subtract subtract(a,b)},{@link #subtract subtract(b,a)})}. * @param a the first collection, must not be null * @param b the second collection, must not be null * @param the generic type that is able to represent the types contained * in both input collections. * @return the symmetric difference of the two collections */ public static Collection disjunction(final Iterable a, final Iterable b) { final SetOperationCardinalityHelper helper = new SetOperationCardinalityHelper<>(a, b); for (final O obj : helper) { helper.setCardinality(obj, helper.max(obj) - helper.min(obj)); } return helper.list(); } /** * Returns a new {@link Collection} containing {@code a - b}. * The cardinality of each element e in the returned {@link Collection} * will be the cardinality of e in a minus the cardinality * of e in b, or zero, whichever is greater. * * @param a the collection to subtract from, must not be null * @param b the collection to subtract, must not be null * @param the generic type that is able to represent the types contained * in both input collections. * @return a new collection with the results * @see Collection#removeAll */ public static Collection subtract(final Iterable a, final Iterable b) { final Predicate p = TruePredicate.truePredicate(); return subtract(a, b, p); } /** * Returns a new {@link Collection} containing a minus a subset of * b. Only the elements of b that satisfy the predicate * condition, p are subtracted from a. * *

The cardinality of each element e in the returned {@link Collection} * that satisfies the predicate condition will be the cardinality of e in a * minus the cardinality of e in b, or zero, whichever is greater.

*

The cardinality of each element e in the returned {@link Collection} that does not * satisfy the predicate condition will be equal to the cardinality of e in a.

* * @param a the collection to subtract from, must not be null * @param b the collection to subtract, must not be null * @param p the condition used to determine which elements of b are * subtracted. * @param the generic type that is able to represent the types contained * in both input collections. * @return a new collection with the results * @since 4.0 * @see Collection#removeAll */ public static Collection subtract(final Iterable a, final Iterable b, final Predicate p) { final ArrayList list = new ArrayList<>(); final HashBag bag = new HashBag<>(); for (final O element : b) { if (p.evaluate(element)) { bag.add(element); } } for (final O element : a) { if (!bag.remove(element, 1)) { list.add(element); } } return list; } /** * Returns true iff all elements of {@code coll2} are also contained * in {@code coll1}. The cardinality of values in {@code coll2} is not taken into account, * which is the same behavior as {@link Collection#containsAll(Collection)}. *

* In other words, this method returns true iff the * {@link #intersection} of coll1 and coll2 has the same cardinality as * the set of unique values from {@code coll2}. In case {@code coll2} is empty, {@code true} * will be returned. *

* This method is intended as a replacement for {@link Collection#containsAll(Collection)} * with a guaranteed runtime complexity of {@code O(n + m)}. Depending on the type of * {@link Collection} provided, this method will be much faster than calling * {@link Collection#containsAll(Collection)} instead, though this will come at the * cost of an additional space complexity O(n). * * @param coll1 the first collection, must not be null * @param coll2 the second collection, must not be null * @return true iff the intersection of the collections has the same cardinality * as the set of unique elements from the second collection * @since 4.0 */ public static boolean containsAll(final Collection coll1, final Collection coll2) { if (coll2.isEmpty()) { return true; } final Iterator it = coll1.iterator(); final Set elementsAlreadySeen = new HashSet<>(); for (final Object nextElement : coll2) { if (elementsAlreadySeen.contains(nextElement)) { continue; } boolean foundCurrentElement = false; while (it.hasNext()) { final Object p = it.next(); elementsAlreadySeen.add(p); if (nextElement == null ? p == null : nextElement.equals(p)) { foundCurrentElement = true; break; } } if (!foundCurrentElement) { return false; } } return true; } /** * Returns true iff at least one element is in both collections. *

* In other words, this method returns true iff the * {@link #intersection} of coll1 and coll2 is not empty. * * @param the type of object to lookup in coll1. * @param coll1 the first collection, must not be null * @param coll2 the second collection, must not be null * @return true iff the intersection of the collections is non-empty * @since 4.2 * @see #intersection */ public static boolean containsAny(final Collection coll1, @SuppressWarnings("unchecked") final T... coll2) { if (coll1.size() < coll2.length) { for (final Object aColl1 : coll1) { if (ArrayUtils.contains(coll2, aColl1)) { return true; } } } else { for (final Object aColl2 : coll2) { if (coll1.contains(aColl2)) { return true; } } } return false; } /** * Returns true iff at least one element is in both collections. *

* In other words, this method returns true iff the * {@link #intersection} of coll1 and coll2 is not empty. * * @param coll1 the first collection, must not be null * @param coll2 the second collection, must not be null * @return true iff the intersection of the collections is non-empty * @since 2.1 * @see #intersection */ public static boolean containsAny(final Collection coll1, final Collection coll2) { if (coll1.size() < coll2.size()) { for (final Object aColl1 : coll1) { if (coll2.contains(aColl1)) { return true; } } } else { for (final Object aColl2 : coll2) { if (coll1.contains(aColl2)) { return true; } } } return false; } /** * Returns a {@link Map} mapping each unique element in the given * {@link Collection} to an {@link Integer} representing the number * of occurrences of that element in the {@link Collection}. *

* Only those elements present in the collection will appear as * keys in the map. * * @param the type of object in the returned {@link Map}. This is a super type of <I>. * @param coll the collection to get the cardinality map for, must not be null * @return the populated cardinality map */ public static Map getCardinalityMap(final Iterable coll) { final Map count = new HashMap<>(); for (final O obj : coll) { final Integer c = count.get(obj); if (c == null) { count.put(obj, Integer.valueOf(1)); } else { count.put(obj, Integer.valueOf(c.intValue() + 1)); } } return count; } /** * Returns {@code true} iff a is a sub-collection of b, * that is, iff the cardinality of e in a is less than or * equal to the cardinality of e in b, for each element e * in a. * * @param a the first (sub?) collection, must not be null * @param b the second (super?) collection, must not be null * @return true iff a is a sub-collection of b * @see #isProperSubCollection * @see Collection#containsAll */ public static boolean isSubCollection(final Collection a, final Collection b) { final CardinalityHelper helper = new CardinalityHelper<>(a, b); for (final Object obj : a) { if (helper.freqA(obj) > helper.freqB(obj)) { return false; } } return true; } /** * Returns {@code true} iff a is a proper sub-collection of b, * that is, iff the cardinality of e in a is less * than or equal to the cardinality of e in b, * for each element e in a, and there is at least one * element f such that the cardinality of f in b * is strictly greater than the cardinality of f in a. *

* The implementation assumes *

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

* That is, iff 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, must not be null * @param b the second collection, must not be null * @return true iff the collections contain the same elements with the same cardinalities. */ public static boolean isEqualCollection(final Collection a, final Collection b) { if(a.size() != b.size()) { return false; } final CardinalityHelper helper = new CardinalityHelper<>(a, b); if(helper.cardinalityA.size() != helper.cardinalityB.size()) { return false; } for( final Object obj : helper.cardinalityA.keySet()) { if(helper.freqA(obj) != helper.freqB(obj)) { return false; } } return true; } /** * Returns {@code true} iff the given {@link Collection}s contain * exactly the same elements with exactly the same cardinalities. *

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

* Note: from version 4.1 onwards this method requires the input * collections and equator to be of compatible type (using bounded wildcards). * Providing incompatible arguments (e.g. by casting to their rawtypes) * will result in a {@code ClassCastException} thrown at runtime. * * @param the element type * @param a the first collection, must not be null * @param b the second collection, must not be null * @param equator the Equator used for testing equality * @return true iff the collections contain the same elements with the same cardinalities. * @throws NullPointerException if the equator is null * @since 4.0 */ public static boolean isEqualCollection(final Collection a, final Collection b, final Equator equator) { if (equator == null) { throw new NullPointerException("Equator must not be null."); } if(a.size() != b.size()) { return false; } @SuppressWarnings({ "unchecked", "rawtypes" }) final Transformer transformer = new Transformer() { @Override public EquatorWrapper transform(final Object input) { return new EquatorWrapper(equator, input); } }; return isEqualCollection(collect(a, transformer), collect(b, transformer)); } /** * Wraps another object and uses the provided Equator to implement * {@link #equals(Object)} and {@link #hashCode()}. *

* This class can be used to store objects into a Map. * * @param the element type * @since 4.0 */ private static class EquatorWrapper { private final Equator equator; private final O object; public EquatorWrapper(final Equator equator, final O object) { this.equator = equator; this.object = object; } public O getObject() { return object; } @Override public boolean equals(final Object obj) { if (!(obj instanceof EquatorWrapper)) { return false; } @SuppressWarnings("unchecked") final EquatorWrapper otherObj = (EquatorWrapper) obj; return equator.equate(object, otherObj.getObject()); } @Override public int hashCode() { return equator.hash(object); } } /** * Returns the number of occurrences of obj in coll. * * @param obj the object to find the cardinality of * @param coll the {@link Iterable} to search * @param the type of object that the {@link Iterable} may contain. * @return the number of occurrences of obj in coll * @throws NullPointerException if coll is null * @deprecated since 4.1, use {@link IterableUtils#frequency(Iterable, Object)} instead. * Be aware that the order of parameters has changed. */ @Deprecated public static int cardinality(final O obj, final Iterable coll) { if (coll == null) { throw new NullPointerException("coll must not be null."); } return IterableUtils.frequency(coll, obj); } /** * Finds the first element in the given collection which matches the given predicate. *

* If the input collection or predicate is null, or no element of the collection * matches the predicate, null is returned. * * @param the type of object the {@link Iterable} contains * @param collection the collection to search, may be null * @param predicate the predicate to use, may be null * @return the first element of the collection which matches the predicate or null if none could be found * @deprecated since 4.1, use {@link IterableUtils#find(Iterable, Predicate)} instead */ @Deprecated public static T find(final Iterable collection, final Predicate predicate) { return predicate != null ? IterableUtils.find(collection, predicate) : null; } /** * Executes the given closure on each element in the collection. *

* If the input collection or closure is null, there is no change made. * * @param the type of object the {@link Iterable} contains * @param the closure type * @param collection the collection to get the input from, may be null * @param closure the closure to perform, may be null * @return closure * @deprecated since 4.1, use {@link IterableUtils#forEach(Iterable, Closure)} instead */ @Deprecated public static > C forAllDo(final Iterable collection, final C closure) { if (closure != null) { IterableUtils.forEach(collection, closure); } return closure; } /** * Executes the given closure on each element in the collection. *

* If the input collection or closure is null, there is no change made. * * @param the type of object the {@link Iterator} contains * @param the closure type * @param iterator the iterator to get the input from, may be null * @param closure the closure to perform, may be null * @return closure * @since 4.0 * @deprecated since 4.1, use {@link IteratorUtils#forEach(Iterator, Closure)} instead */ @Deprecated public static > C forAllDo(final Iterator iterator, final C closure) { if (closure != null) { IteratorUtils.forEach(iterator, closure); } return closure; } /** * Executes the given closure on each but the last element in the collection. *

* If the input collection or closure is null, there is no change made. * * @param the type of object the {@link Iterable} contains * @param the closure type * @param collection the collection to get the input from, may be null * @param closure the closure to perform, may be null * @return the last element in the collection, or null if either collection or closure is null * @since 4.0 * @deprecated since 4.1, use {@link IterableUtils#forEachButLast(Iterable, Closure)} instead */ @Deprecated public static > T forAllButLastDo(final Iterable collection, final C closure) { return closure != null ? IterableUtils.forEachButLast(collection, closure) : null; } /** * Executes the given closure on each but the last element in the collection. *

* If the input collection or closure is null, there is no change made. * * @param the type of object the {@link Collection} contains * @param the closure type * @param iterator the iterator to get the input from, may be null * @param closure the closure to perform, may be null * @return the last element in the collection, or null if either iterator or closure is null * @since 4.0 * @deprecated since 4.1, use {@link IteratorUtils#forEachButLast(Iterator, Closure)} instead */ @Deprecated public static > T forAllButLastDo(final Iterator iterator, final C closure) { return closure != null ? IteratorUtils.forEachButLast(iterator, closure) : null; } /** * Filter the collection by applying a Predicate to each element. If the * predicate returns false, remove the element. *

* If the input collection or predicate is null, there is no change made. * * @param the type of object the {@link Iterable} contains * @param collection the collection to get the input from, may be null * @param predicate the predicate to use as a filter, may be null * @return true if the collection is modified by this call, false otherwise. */ public static boolean filter(final Iterable collection, final Predicate predicate) { boolean result = false; if (collection != null && predicate != null) { for (final Iterator it = collection.iterator(); it.hasNext();) { if (!predicate.evaluate(it.next())) { it.remove(); result = true; } } } return result; } /** * Filter the collection by applying a Predicate to each element. If the * predicate returns true, remove the element. *

* This is equivalent to

filter(collection, PredicateUtils.notPredicate(predicate))
* if predicate is != null. *

* If the input collection or predicate is null, there is no change made. * * @param the type of object the {@link Iterable} contains * @param collection the collection to get the input from, may be null * @param predicate the predicate to use as a filter, may be null * @return true if the collection is modified by this call, false otherwise. */ public static boolean filterInverse(final Iterable collection, final Predicate predicate) { return filter(collection, predicate == null ? null : PredicateUtils.notPredicate(predicate)); } /** * Transform the collection by applying a Transformer to each element. *

* If the input collection or transformer is null, there is no change made. *

* This routine is best for Lists, for which set() is used to do the * transformations "in place." For other Collections, clear() and addAll() * are used to replace elements. *

* If the input collection controls its input, such as a Set, and the * Transformer creates duplicates (or are otherwise invalid), the collection * may reduce in size due to calling this method. * * @param the type of object the {@link Collection} contains * @param collection the {@link Collection} to get the input from, may be null * @param transformer the transformer to perform, may be null */ public static void transform(final Collection collection, final Transformer transformer) { if (collection != null && transformer != null) { if (collection instanceof List) { final List list = (List) collection; for (final ListIterator it = list.listIterator(); it.hasNext();) { it.set(transformer.transform(it.next())); } } else { final Collection resultCollection = collect(collection, transformer); collection.clear(); collection.addAll(resultCollection); } } } /** * Counts the number of elements in the input collection that match the * predicate. *

* A null collection or predicate matches no elements. * * @param the type of object the {@link Iterable} contains * @param input the {@link Iterable} to get the input from, may be null * @param predicate the predicate to use, may be null * @return the number of matches for the predicate in the collection * @deprecated since 4.1, use {@link IterableUtils#countMatches(Iterable, Predicate)} instead */ @Deprecated public static int countMatches(final Iterable input, final Predicate predicate) { return predicate == null ? 0 : (int) IterableUtils.countMatches(input, predicate); } /** * Answers true if a predicate is true for at least one element of a * collection. *

* A null collection or predicate returns false. * * @param the type of object the {@link Iterable} contains * @param input the {@link Iterable} to get the input from, may be null * @param predicate the predicate to use, may be null * @return true if at least one element of the collection matches the predicate * @deprecated since 4.1, use {@link IterableUtils#matchesAny(Iterable, Predicate)} instead */ @Deprecated public static boolean exists(final Iterable input, final Predicate predicate) { return predicate != null && IterableUtils.matchesAny(input, predicate); } /** * Answers true if a predicate is true for every element of a * collection. *

* A null predicate returns false.
* A null or empty collection returns true. * * @param the type of object the {@link Iterable} contains * @param input the {@link Iterable} to get the input from, may be null * @param predicate the predicate to use, may be null * @return true if every element of the collection matches the predicate or if the * collection is empty, false otherwise * @since 4.0 * @deprecated since 4.1, use {@link IterableUtils#matchesAll(Iterable, Predicate)} instead */ @Deprecated public static boolean matchesAll(final Iterable input, final Predicate predicate) { return predicate != null && IterableUtils.matchesAll(input, predicate); } /** * Selects all elements from input collection which match the given * predicate into an output collection. *

* A null predicate matches no elements. * * @param the type of object the {@link Iterable} contains * @param inputCollection the collection to get the input from, may not be null * @param predicate the predicate to use, may be null * @return the elements matching the predicate (new list) * @throws NullPointerException if the input collection is null */ public static Collection select(final Iterable inputCollection, final Predicate predicate) { final Collection answer = inputCollection instanceof Collection ? new ArrayList(((Collection) inputCollection).size()) : new ArrayList(); return select(inputCollection, predicate, answer); } /** * Selects all elements from input collection which match the given * predicate and adds them to outputCollection. *

* If the input collection or predicate is null, there is no change to the * output collection. * * @param the type of object the {@link Iterable} contains * @param the type of the output {@link Collection} * @param inputCollection the collection to get the input from, may be null * @param predicate the predicate to use, may be null * @param outputCollection the collection to output into, may not be null if the inputCollection * and predicate or not null * @return the outputCollection */ public static > R select(final Iterable inputCollection, final Predicate predicate, final R outputCollection) { if (inputCollection != null && predicate != null) { for (final O item : inputCollection) { if (predicate.evaluate(item)) { outputCollection.add(item); } } } return outputCollection; } /** * Selects all elements from inputCollection into an output and rejected collection, * based on the evaluation of the given predicate. *

* Elements matching the predicate are added to the outputCollection, * all other elements are added to the rejectedCollection. *

* If the input predicate is null, no elements are added to * outputCollection or rejectedCollection. *

* Note: calling the method is equivalent to the following code snippet: *

     *   select(inputCollection, predicate, outputCollection);
     *   selectRejected(inputCollection, predicate, rejectedCollection);
     * 
* * @param the type of object the {@link Iterable} contains * @param the type of the output {@link Collection} * @param inputCollection the collection to get the input from, may be null * @param predicate the predicate to use, may be null * @param outputCollection the collection to output selected elements into, may not be null if the * inputCollection and predicate are not null * @param rejectedCollection the collection to output rejected elements into, may not be null if the * inputCollection or predicate are not null * @return the outputCollection * @since 4.1 */ public static > R select(final Iterable inputCollection, final Predicate predicate, final R outputCollection, final R rejectedCollection) { if (inputCollection != null && predicate != null) { for (final O element : inputCollection) { if (predicate.evaluate(element)) { outputCollection.add(element); } else { rejectedCollection.add(element); } } } return outputCollection; } /** * Selects all elements from inputCollection which don't match the given * predicate into an output collection. *

* If the input predicate is null, the result is an empty * list. * * @param the type of object the {@link Iterable} contains * @param inputCollection the collection to get the input from, may not be null * @param predicate the predicate to use, may be null * @return the elements not matching the predicate (new list) * @throws NullPointerException if the input collection is null */ public static Collection selectRejected(final Iterable inputCollection, final Predicate predicate) { final Collection answer = inputCollection instanceof Collection ? new ArrayList(((Collection) inputCollection).size()) : new ArrayList(); return selectRejected(inputCollection, predicate, answer); } /** * Selects all elements from inputCollection which don't match the given * predicate and adds them to outputCollection. *

* If the input predicate is null, no elements are added to * outputCollection. * * @param the type of object the {@link Iterable} contains * @param the type of the output {@link Collection} * @param inputCollection the collection to get the input from, may be null * @param predicate the predicate to use, may be null * @param outputCollection the collection to output into, may not be null if the inputCollection * and predicate or not null * @return outputCollection */ public static > R selectRejected(final Iterable inputCollection, final Predicate predicate, final R outputCollection) { if (inputCollection != null && predicate != null) { for (final O item : inputCollection) { if (!predicate.evaluate(item)) { outputCollection.add(item); } } } return outputCollection; } /** * Returns a new Collection containing all elements of the input collection * transformed by the given transformer. *

* If the input collection or transformer is null, the result is an empty list. * * @param the type of object in the input collection * @param the type of object in the output collection * @param inputCollection the collection to get the input from, may not be null * @param transformer the transformer to use, may be null * @return the transformed result (new list) * @throws NullPointerException if the input collection is null */ public static Collection collect(final Iterable inputCollection, final Transformer transformer) { final Collection answer = inputCollection instanceof Collection ? new ArrayList(((Collection) inputCollection).size()) : new ArrayList(); return collect(inputCollection, transformer, answer); } /** * Transforms all elements from the input iterator with the given transformer * and adds them to the output collection. *

* If the input iterator or transformer is null, the result is an empty list. * * @param the type of object in the input collection * @param the type of object in the output collection * @param inputIterator the iterator to get the input from, may be null * @param transformer the transformer to use, may be null * @return the transformed result (new list) */ public static Collection collect(final Iterator inputIterator, final Transformer transformer) { return collect(inputIterator, transformer, new ArrayList()); } /** * Transforms all elements from input collection with the given transformer * and adds them to the output collection. *

* If the input collection or transformer is null, there is no change to the * output collection. * * @param the type of object in the input collection * @param the type of object in the output collection * @param the type of the output collection * @param inputCollection the collection to get the input from, may be null * @param transformer the transformer to use, may be null * @param outputCollection the collection to output into, may not be null if inputCollection * and transformer are not null * @return the output collection with the transformed input added * @throws NullPointerException if the outputCollection is null and both, inputCollection and * transformer are not null */ public static > R collect(final Iterable inputCollection, final Transformer transformer, final R outputCollection) { if (inputCollection != null) { return collect(inputCollection.iterator(), transformer, outputCollection); } return outputCollection; } /** * Transforms all elements from the input iterator with the given transformer * and adds them to the output collection. *

* If the input iterator or transformer is null, there is no change to the * output collection. * * @param the type of object in the input collection * @param the type of object in the output collection * @param the type of the output collection * @param inputIterator the iterator to get the input from, may be null * @param transformer the transformer to use, may be null * @param outputCollection the collection to output into, may not be null if inputIterator * and transformer are not null * @return the outputCollection with the transformed input added * @throws NullPointerException if the output collection is null and both, inputIterator and * transformer are not null */ public static > R collect(final Iterator inputIterator, final Transformer transformer, final R outputCollection) { if (inputIterator != null && transformer != null) { while (inputIterator.hasNext()) { final I item = inputIterator.next(); final O value = transformer.transform(item); outputCollection.add(value); } } return outputCollection; } //----------------------------------------------------------------------- /** * Adds an element to the collection unless the element is null. * * @param the type of object the {@link Collection} contains * @param collection the collection to add to, must not be null * @param object the object to add, if null it will not be added * @return true if the collection changed * @throws NullPointerException if the collection is null * @since 3.2 */ public static boolean addIgnoreNull(final Collection collection, final T object) { if (collection == null) { throw new NullPointerException("The collection must not be null"); } return object != null && collection.add(object); } /** * Adds all elements in the {@link Iterable} to the given collection. If the * {@link Iterable} is a {@link Collection} then it is cast and will be * added using {@link Collection#addAll(Collection)} instead of iterating. * * @param the type of object the {@link Collection} contains * @param collection the collection to add to, must not be null * @param iterable the iterable of elements to add, must not be null * @return a boolean indicating whether the collection has changed or not. * @throws NullPointerException if the collection or iterator is null */ public static boolean addAll(final Collection collection, final Iterable iterable) { if (iterable instanceof Collection) { return collection.addAll((Collection) iterable); } return addAll(collection, iterable.iterator()); } /** * Adds all elements in the iteration to the given collection. * * @param the type of object the {@link Collection} contains * @param collection the collection to add to, must not be null * @param iterator the iterator of elements to add, must not be null * @return a boolean indicating whether the collection has changed or not. * @throws NullPointerException if the collection or iterator is null */ public static boolean addAll(final Collection collection, final Iterator iterator) { boolean changed = false; while (iterator.hasNext()) { changed |= collection.add(iterator.next()); } return changed; } /** * Adds all elements in the enumeration to the given collection. * * @param the type of object the {@link Collection} contains * @param collection the collection to add to, must not be null * @param enumeration the enumeration of elements to add, must not be null * @return {@code true} if the collections was changed, {@code false} otherwise * @throws NullPointerException if the collection or enumeration is null */ public static boolean addAll(final Collection collection, final Enumeration enumeration) { boolean changed = false; while (enumeration.hasMoreElements()) { changed |= collection.add(enumeration.nextElement()); } return changed; } /** * Adds all elements in the array to the given collection. * * @param the type of object the {@link Collection} contains * @param collection the collection to add to, must not be null * @param elements the array of elements to add, must not be null * @return {@code true} if the collection was changed, {@code false} otherwise * @throws NullPointerException if the collection or array is null */ public static boolean addAll(final Collection collection, final C... elements) { boolean changed = false; for (final C element : elements) { changed |= collection.add(element); } return changed; } /** * Returns the index-th value in {@link Iterator}, throwing * IndexOutOfBoundsException if there is no such element. *

* The Iterator is advanced to index (or to the end, if * index exceeds the number of entries) as a side effect of this method. * * @param iterator the iterator to get a value from * @param index the index to get * @param the type of object in the {@link Iterator} * @return the object at the specified index * @throws IndexOutOfBoundsException if the index is invalid * @throws IllegalArgumentException if the object type is invalid * @deprecated since 4.1, use {@code IteratorUtils.get(Iterator, int)} instead */ @Deprecated public static T get(final Iterator iterator, final int index) { return IteratorUtils.get(iterator, index); } /** * Ensures an index is not negative. * @param index the index to check. * @throws IndexOutOfBoundsException if the index is negative. */ static void checkIndexBounds(final int index) { if (index < 0) { throw new IndexOutOfBoundsException("Index cannot be negative: " + index); } } /** * Returns the index-th value in the iterable's {@link Iterator}, throwing * IndexOutOfBoundsException if there is no such element. *

* If the {@link Iterable} is a {@link List}, then it will use {@link List#get(int)}. * * @param iterable the {@link Iterable} to get a value from * @param index the index to get * @param the type of object in the {@link Iterable}. * @return the object at the specified index * @throws IndexOutOfBoundsException if the index is invalid * @deprecated since 4.1, use {@code IterableUtils.get(Iterable, int)} instead */ @Deprecated public static T get(final Iterable iterable, final int index) { return IterableUtils.get(iterable, index); } /** * Returns the index-th value in object, throwing * IndexOutOfBoundsException if there is no such element or * IllegalArgumentException if object is not an * instance of one of the supported types. *

* The supported types, and associated semantics are: *

    *
  • Map -- the value returned is the Map.Entry in position * index in the map's entrySet iterator, * if there is such an entry.
  • *
  • List -- this method is equivalent to the list's get method.
  • *
  • Array -- the index-th array entry is returned, * if there is such an entry; otherwise an IndexOutOfBoundsException * is thrown.
  • *
  • Collection -- the value returned is the index-th object * returned by the collection's default iterator, if there is such an element.
  • *
  • Iterator or Enumeration -- the value returned is the * index-th object in the Iterator/Enumeration, if there * is such an element. The Iterator/Enumeration is advanced to * index (or to the end, if index exceeds the * number of entries) as a side effect of this method.
  • *
* * @param object the object to get a value from * @param index the index to get * @return the object at the specified index * @throws IndexOutOfBoundsException if the index is invalid * @throws IllegalArgumentException if the object type is invalid */ public static Object get(final Object object, final int index) { final int i = index; if (i < 0) { throw new IndexOutOfBoundsException("Index cannot be negative: " + i); } if (object instanceof Map) { final Map map = (Map) object; final Iterator iterator = map.entrySet().iterator(); return IteratorUtils.get(iterator, i); } else if (object instanceof Object[]) { return ((Object[]) object)[i]; } else if (object instanceof Iterator) { final Iterator it = (Iterator) object; return IteratorUtils.get(it, i); } else if (object instanceof Iterable) { final Iterable iterable = (Iterable) object; return IterableUtils.get(iterable, i); } else if (object instanceof Enumeration) { final Enumeration it = (Enumeration) object; return EnumerationUtils.get(it, i); } else if (object == null) { throw new IllegalArgumentException("Unsupported object type: null"); } else { try { return Array.get(object, i); } catch (final IllegalArgumentException ex) { throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName()); } } } /** * Returns the index-th Map.Entry in the map's entrySet, * throwing IndexOutOfBoundsException if there is no such element. * * @param the key type in the {@link Map} * @param the key type in the {@link Map} * @param map the object to get a value from * @param index the index to get * @return the object at the specified index * @throws IndexOutOfBoundsException if the index is invalid */ public static Map.Entry get(final Map map, final int index) { checkIndexBounds(index); return get(map.entrySet(), index); } /** * Gets the size of the collection/iterator specified. *

* This method can handles objects as follows *

    *
  • Collection - the collection size *
  • Map - the map size *
  • Array - the array size *
  • Iterator - the number of elements remaining in the iterator *
  • Enumeration - the number of elements remaining in the enumeration *
* * @param object the object to get the size of, may be null * @return the size of the specified collection or 0 if the object was null * @throws IllegalArgumentException thrown if object is not recognized * @since 3.1 */ public static int size(final Object object) { if (object == null) { return 0; } int total = 0; if (object instanceof Map) { total = ((Map) object).size(); } else if (object instanceof Collection) { total = ((Collection) object).size(); } else if (object instanceof Iterable) { total = IterableUtils.size((Iterable) object); } else if (object instanceof Object[]) { total = ((Object[]) object).length; } else if (object instanceof Iterator) { total = IteratorUtils.size((Iterator) object); } else if (object instanceof Enumeration) { final Enumeration it = (Enumeration) object; while (it.hasMoreElements()) { total++; it.nextElement(); } } else { try { total = Array.getLength(object); } catch (final IllegalArgumentException ex) { throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName()); } } return total; } /** * Checks if the specified collection/array/iterator is empty. *

* This method can handles objects as follows *

    *
  • Collection - via collection isEmpty *
  • Map - via map isEmpty *
  • Array - using array size *
  • Iterator - via hasNext *
  • Enumeration - via hasMoreElements *
*

* Note: This method is named to avoid clashing with * {@link #isEmpty(Collection)}. * * @param object the object to get the size of, may be null * @return true if empty or null * @throws IllegalArgumentException thrown if object is not recognized * @since 3.2 */ public static boolean sizeIsEmpty(final Object object) { if (object == null) { return true; } else if (object instanceof Collection) { return ((Collection) object).isEmpty(); } else if (object instanceof Iterable) { return IterableUtils.isEmpty((Iterable) object); } else if (object instanceof Map) { return ((Map) object).isEmpty(); } else if (object instanceof Object[]) { return ((Object[]) object).length == 0; } else if (object instanceof Iterator) { return ((Iterator) object).hasNext() == false; } else if (object instanceof Enumeration) { return ((Enumeration) object).hasMoreElements() == false; } else { try { return Array.getLength(object) == 0; } catch (final IllegalArgumentException ex) { throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName()); } } } //----------------------------------------------------------------------- /** * Null-safe check if the specified collection is empty. *

* Null returns true. * * @param coll the collection to check, may be null * @return true if empty or null * @since 3.2 */ public static boolean isEmpty(final Collection coll) { return coll == null || coll.isEmpty(); } /** * Null-safe check if the specified collection is not empty. *

* Null returns false. * * @param coll the collection to check, may be null * @return true if non-null and non-empty * @since 3.2 */ public static boolean isNotEmpty(final Collection coll) { return !isEmpty(coll); } //----------------------------------------------------------------------- /** * Reverses the order of the given array. * * @param array the array to reverse */ public static void reverseArray(final Object[] array) { int i = 0; int j = array.length - 1; Object tmp; while (j > i) { tmp = array[j]; array[j] = array[i]; array[i] = tmp; j--; i++; } } /** * Returns true if no more elements can be added to the Collection. *

* This method uses the {@link BoundedCollection} interface to determine the * full status. If the collection does not implement this interface then * false is returned. *

* The collection does not have to implement this interface directly. * If the collection has been decorated using the decorators subpackage * then these will be removed to access the BoundedCollection. * * @param coll the collection to check * @return true if the BoundedCollection is full * @throws NullPointerException if the collection is null */ public static boolean isFull(final Collection coll) { if (coll == null) { throw new NullPointerException("The collection must not be null"); } if (coll instanceof BoundedCollection) { return ((BoundedCollection) coll).isFull(); } try { final BoundedCollection bcoll = UnmodifiableBoundedCollection.unmodifiableBoundedCollection(coll); return bcoll.isFull(); } catch (final IllegalArgumentException ex) { return false; } } /** * Get the maximum number of elements that the Collection can contain. *

* This method uses the {@link BoundedCollection} interface to determine the * maximum size. If the collection does not implement this interface then * -1 is returned. *

* The collection does not have to implement this interface directly. * If the collection has been decorated using the decorators subpackage * then these will be removed to access the BoundedCollection. * * @param coll the collection to check * @return the maximum size of the BoundedCollection, -1 if no maximum size * @throws NullPointerException if the collection is null */ public static int maxSize(final Collection coll) { if (coll == null) { throw new NullPointerException("The collection must not be null"); } if (coll instanceof BoundedCollection) { return ((BoundedCollection) coll).maxSize(); } try { final BoundedCollection bcoll = UnmodifiableBoundedCollection.unmodifiableBoundedCollection(coll); return bcoll.maxSize(); } catch (final IllegalArgumentException ex) { return -1; } } //----------------------------------------------------------------------- /** * Merges two sorted Collections, a and b, into a single, sorted List * such that the natural ordering of the elements is retained. *

* Uses the standard O(n) merge algorithm for combining two sorted lists. * * @param the element type * @param a the first collection, must not be null * @param b the second collection, must not be null * @return a new sorted List, containing the elements of Collection a and b * @throws NullPointerException if either collection is null * @since 4.0 */ public static > List collate(final Iterable a, final Iterable b) { return collate(a, b, ComparatorUtils.naturalComparator(), true); } /** * Merges two sorted Collections, a and b, into a single, sorted List * such that the natural ordering of the elements is retained. *

* Uses the standard O(n) merge algorithm for combining two sorted lists. * * @param the element type * @param a the first collection, must not be null * @param b the second collection, must not be null * @param includeDuplicates if {@code true} duplicate elements will be retained, otherwise * they will be removed in the output collection * @return a new sorted List, containing the elements of Collection a and b * @throws NullPointerException if either collection is null * @since 4.0 */ public static > List collate(final Iterable a, final Iterable b, final boolean includeDuplicates) { return collate(a, b, ComparatorUtils.naturalComparator(), includeDuplicates); } /** * Merges two sorted Collections, a and b, into a single, sorted List * such that the ordering of the elements according to Comparator c is retained. *

* Uses the standard O(n) merge algorithm for combining two sorted lists. * * @param the element type * @param a the first collection, must not be null * @param b the second collection, must not be null * @param c the comparator to use for the merge. * @return a new sorted List, containing the elements of Collection a and b * @throws NullPointerException if either collection or the comparator is null * @since 4.0 */ public static List collate(final Iterable a, final Iterable b, final Comparator c) { return collate(a, b, c, true); } /** * Merges two sorted Collections, a and b, into a single, sorted List * such that the ordering of the elements according to Comparator c is retained. *

* Uses the standard O(n) merge algorithm for combining two sorted lists. * * @param the element type * @param a the first collection, must not be null * @param b the second collection, must not be null * @param c the comparator to use for the merge. * @param includeDuplicates if {@code true} duplicate elements will be retained, otherwise * they will be removed in the output collection * @return a new sorted List, containing the elements of Collection a and b * @throws NullPointerException if either collection or the comparator is null * @since 4.0 */ public static List collate(final Iterable a, final Iterable b, final Comparator c, final boolean includeDuplicates) { if (a == null || b == null) { throw new NullPointerException("The collections must not be null"); } if (c == null) { throw new NullPointerException("The comparator must not be null"); } // if both Iterables are a Collection, we can estimate the size final int totalSize = a instanceof Collection && b instanceof Collection ? Math.max(1, ((Collection) a).size() + ((Collection) b).size()) : 10; final Iterator iterator = new CollatingIterator<>(c, a.iterator(), b.iterator()); if (includeDuplicates) { return IteratorUtils.toList(iterator, totalSize); } final ArrayList mergedList = new ArrayList<>(totalSize); O lastItem = null; while (iterator.hasNext()) { final O item = iterator.next(); if (lastItem == null || !lastItem.equals(item)) { mergedList.add(item); } lastItem = item; } mergedList.trimToSize(); return mergedList; } //----------------------------------------------------------------------- /** * Returns a {@link Collection} of all the permutations of the input collection. *

* NOTE: the number of permutations of a given collection is equal to n!, where * n is the size of the collection. Thus, the resulting collection will become * very large for collections > 10 (e.g. 10! = 3628800, 15! = 1307674368000). *

* For larger collections it is advised to use a {@link PermutationIterator} to * iterate over all permutations. * * @see PermutationIterator * * @param the element type * @param collection the collection to create permutations for, may not be null * @return an unordered collection of all permutations of the input collection * @throws NullPointerException if collection is null * @since 4.0 */ public static Collection> permutations(final Collection collection) { final PermutationIterator it = new PermutationIterator<>(collection); final Collection> result = new ArrayList<>(); while (it.hasNext()) { result.add(it.next()); } return result; } //----------------------------------------------------------------------- /** * Returns a collection containing all the elements in collection * that are also in retain. The cardinality of an element e * in the returned collection is the same as the cardinality of e * in collection unless retain does not contain e, in which * case the cardinality is zero. This method is useful if you do not wish to modify * the collection c and thus cannot call c.retainAll(retain);. *

* This implementation iterates over collection, checking each element in * turn to see if it's contained in retain. If it's contained, it's added * to the returned list. As a consequence, it is advised to use a collection type for * retain that provides a fast (e.g. O(1)) implementation of * {@link Collection#contains(Object)}. * * @param the type of object the {@link Collection} contains * @param collection the collection whose contents are the target of the #retailAll operation * @param retain the collection containing the elements to be retained in the returned collection * @return a Collection containing all the elements of collection * that occur at least once in retain. * @throws NullPointerException if either parameter is null * @since 3.2 */ public static Collection retainAll(final Collection collection, final Collection retain) { return ListUtils.retainAll(collection, retain); } /** * Returns a collection containing all the elements in * collection that are also in retain. The * cardinality of an element e in the returned collection is * the same as the cardinality of e in collection * unless retain does not contain e, in which case * the cardinality is zero. This method is useful if you do not wish to * modify the collection c and thus cannot call * c.retainAll(retain);. *

* Moreover this method uses an {@link Equator} instead of * {@link Object#equals(Object)} to determine the equality of the elements * in collection and retain. Hence this method is * useful in cases where the equals behavior of an object needs to be * modified without changing the object itself. * * @param the type of object the {@link Collection} contains * @param collection the collection whose contents are the target of the {@code retainAll} operation * @param retain the collection containing the elements to be retained in the returned collection * @param equator the Equator used for testing equality * @return a Collection containing all the elements of collection * that occur at least once in retain according to the equator * @throws NullPointerException if any of the parameters is null * @since 4.1 */ public static Collection retainAll(final Iterable collection, final Iterable retain, final Equator equator) { final Transformer> transformer = new Transformer>() { @Override public EquatorWrapper transform(final E input) { return new EquatorWrapper<>(equator, input); } }; final Set> retainSet = collect(retain, transformer, new HashSet>()); final List list = new ArrayList<>(); for (final E element : collection) { if (retainSet.contains(new EquatorWrapper<>(equator, element))) { list.add(element); } } return list; } /** * Removes the elements in remove from collection. That is, this * method returns a collection containing all the elements in c * that are not in remove. The cardinality of an element e * in the returned collection is the same as the cardinality of e * in collection unless remove contains e, in which * case the cardinality is zero. This method is useful if you do not wish to modify * the collection c and thus cannot call collection.removeAll(remove);. *

* This implementation iterates over collection, checking each element in * turn to see if it's contained in remove. If it's not contained, it's added * to the returned list. As a consequence, it is advised to use a collection type for * remove that provides a fast (e.g. O(1)) implementation of * {@link Collection#contains(Object)}. * * @param the type of object the {@link Collection} contains * @param collection the collection from which items are removed (in the returned collection) * @param remove the items to be removed from the returned collection * @return a Collection containing all the elements of collection except * any elements that also occur in remove. * @throws NullPointerException if either parameter is null * @since 4.0 (method existed in 3.2 but was completely broken) */ public static Collection removeAll(final Collection collection, final Collection remove) { return ListUtils.removeAll(collection, remove); } /** * Removes all elements in remove from collection. * That is, this method returns a collection containing all the elements in * collection that are not in remove. The * cardinality of an element e in the returned collection is * the same as the cardinality of e in collection * unless remove contains e, in which case the * cardinality is zero. This method is useful if you do not wish to modify * the collection c and thus cannot call * collection.removeAll(remove). *

* Moreover this method uses an {@link Equator} instead of * {@link Object#equals(Object)} to determine the equality of the elements * in collection and remove. Hence this method is * useful in cases where the equals behavior of an object needs to be * modified without changing the object itself. * * @param the type of object the {@link Collection} contains * @param collection the collection from which items are removed (in the returned collection) * @param remove the items to be removed from the returned collection * @param equator the Equator used for testing equality * @return a Collection containing all the elements of collection * except any element that if equal according to the equator * @throws NullPointerException if any of the parameters is null * @since 4.1 */ public static Collection removeAll(final Iterable collection, final Iterable remove, final Equator equator) { final Transformer> transformer = new Transformer>() { @Override public EquatorWrapper transform(final E input) { return new EquatorWrapper<>(equator, input); } }; final Set> removeSet = collect(remove, transformer, new HashSet>()); final List list = new ArrayList<>(); for (final E element : collection) { if (!removeSet.contains(new EquatorWrapper<>(equator, element))) { list.add(element); } } return list; } //----------------------------------------------------------------------- /** * Returns a synchronized collection backed by the given collection. *

* You must manually synchronize on the returned buffer's iterator to * avoid non-deterministic behavior: * *

     * Collection c = CollectionUtils.synchronizedCollection(myCollection);
     * synchronized (c) {
     *     Iterator i = c.iterator();
     *     while (i.hasNext()) {
     *         process (i.next());
     *     }
     * }
     * 
* * This method uses the implementation in the decorators subpackage. * * @param the type of object the {@link Collection} contains * @param collection the collection to synchronize, must not be null * @return a synchronized collection backed by the given collection * @throws NullPointerException if the collection is null * @deprecated since 4.1, use {@link java.util.Collections#synchronizedCollection(Collection)} instead */ @Deprecated public static Collection synchronizedCollection(final Collection collection) { return SynchronizedCollection.synchronizedCollection(collection); } /** * Returns an unmodifiable collection backed by the given collection. *

* This method uses the implementation in the decorators subpackage. * * @param the type of object the {@link Collection} contains * @param collection the collection to make unmodifiable, must not be null * @return an unmodifiable collection backed by the given collection * @throws NullPointerException if the collection is null * @deprecated since 4.1, use {@link java.util.Collections#unmodifiableCollection(Collection)} instead */ @Deprecated public static Collection unmodifiableCollection(final Collection collection) { return UnmodifiableCollection.unmodifiableCollection(collection); } /** * Returns a predicated (validating) collection backed by the given collection. *

* Only objects that pass the test in the given predicate can be added to the collection. * Trying to add an invalid object results in an IllegalArgumentException. * It is important not to use the original collection after invoking this method, * as it is a backdoor for adding invalid objects. * * @param the type of objects in the Collection. * @param collection the collection to predicate, must not be null * @param predicate the predicate for the collection, must not be null * @return a predicated collection backed by the given collection * @throws NullPointerException if the Collection is null */ public static Collection predicatedCollection(final Collection collection, final Predicate predicate) { return PredicatedCollection.predicatedCollection(collection, predicate); } /** * Returns a transformed bag backed by the given collection. *

* Each object is passed through the transformer as it is added to the * Collection. It is important not to use the original collection after invoking this * method, as it is a backdoor for adding untransformed objects. *

* Existing entries in the specified collection will not be transformed. * If you want that behaviour, see {@link TransformedCollection#transformedCollection}. * * @param the type of object the {@link Collection} contains * @param collection the collection to predicate, must not be null * @param transformer the transformer for the collection, must not be null * @return a transformed collection backed by the given collection * @throws NullPointerException if the Collection or Transformer is null */ public static Collection transformingCollection(final Collection collection, final Transformer transformer) { return TransformedCollection.transformingCollection(collection, transformer); } /** * Extract the lone element of the specified Collection. * @param collection type * @param collection to read * @return sole member of collection * @throws NullPointerException if collection is null * @throws IllegalArgumentException if collection is empty or contains more than one element * @since 4.0 */ public static E extractSingleton(final Collection collection) { if (collection == null) { throw new NullPointerException("Collection must not be null."); } if (collection.size() != 1) { throw new IllegalArgumentException("Can extract singleton only when collection size == 1"); } return collection.iterator().next(); } }