001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.collections4;
018
019import java.lang.reflect.Array;
020import java.util.ArrayList;
021import java.util.Collection;
022import java.util.Collections;
023import java.util.Comparator;
024import java.util.Enumeration;
025import java.util.HashMap;
026import java.util.HashSet;
027import java.util.Iterator;
028import java.util.List;
029import java.util.ListIterator;
030import java.util.Map;
031import java.util.Set;
032
033import org.apache.commons.collections4.bag.HashBag;
034import org.apache.commons.collections4.collection.PredicatedCollection;
035import org.apache.commons.collections4.collection.SynchronizedCollection;
036import org.apache.commons.collections4.collection.TransformedCollection;
037import org.apache.commons.collections4.collection.UnmodifiableBoundedCollection;
038import org.apache.commons.collections4.collection.UnmodifiableCollection;
039import org.apache.commons.collections4.functors.TruePredicate;
040import org.apache.commons.collections4.iterators.CollatingIterator;
041import org.apache.commons.collections4.iterators.PermutationIterator;
042
043/**
044 * Provides utility methods and decorators for {@link Collection} instances.
045 * <p>
046 * Various utility methods might put the input objects into a Set/Map/Bag. In case
047 * the input objects override {@link Object#equals(Object)}, it is mandatory that
048 * the general contract of the {@link Object#hashCode()} method is maintained.
049 * <p>
050 * NOTE: From 4.0, method parameters will take {@link Iterable} objects when possible.
051 *
052 * @since 1.0
053 */
054public class CollectionUtils {
055
056    /**
057     * Helper class to easily access cardinality properties of two collections.
058     * @param <O>  the element type
059     */
060    private static class CardinalityHelper<O> {
061
062        /** Contains the cardinality for each object in collection A. */
063        final Map<O, Integer> cardinalityA;
064
065        /** Contains the cardinality for each object in collection B. */
066        final Map<O, Integer> cardinalityB;
067
068        /**
069         * Create a new CardinalityHelper for two collections.
070         * @param a  the first collection
071         * @param b  the second collection
072         */
073        public CardinalityHelper(final Iterable<? extends O> a, final Iterable<? extends O> b) {
074            cardinalityA = CollectionUtils.<O>getCardinalityMap(a);
075            cardinalityB = CollectionUtils.<O>getCardinalityMap(b);
076        }
077
078        /**
079         * Returns the maximum frequency of an object.
080         * @param obj  the object
081         * @return the maximum frequency of the object
082         */
083        public final int max(final Object obj) {
084            return Math.max(freqA(obj), freqB(obj));
085        }
086
087        /**
088         * Returns the minimum frequency of an object.
089         * @param obj  the object
090         * @return the minimum frequency of the object
091         */
092        public final int min(final Object obj) {
093            return Math.min(freqA(obj), freqB(obj));
094        }
095
096        /**
097         * Returns the frequency of this object in collection A.
098         * @param obj  the object
099         * @return the frequency of the object in collection A
100         */
101        public int freqA(final Object obj) {
102            return getFreq(obj, cardinalityA);
103        }
104
105        /**
106         * Returns the frequency of this object in collection B.
107         * @param obj  the object
108         * @return the frequency of the object in collection B
109         */
110        public int freqB(final Object obj) {
111            return getFreq(obj, cardinalityB);
112        }
113
114        private int getFreq(final Object obj, final Map<?, Integer> freqMap) {
115            final Integer count = freqMap.get(obj);
116            if (count != null) {
117                return count.intValue();
118            }
119            return 0;
120        }
121    }
122
123    /**
124     * Helper class for set-related operations, e.g. union, subtract, intersection.
125     * @param <O>  the element type
126     */
127    private static class SetOperationCardinalityHelper<O> extends CardinalityHelper<O> implements Iterable<O> {
128
129        /** Contains the unique elements of the two collections. */
130        private final Set<O> elements;
131
132        /** Output collection. */
133        private final List<O> newList;
134
135        /**
136         * Create a new set operation helper from the two collections.
137         * @param a  the first collection
138         * @param b  the second collection
139         */
140        public SetOperationCardinalityHelper(final Iterable<? extends O> a, final Iterable<? extends O> b) {
141            super(a, b);
142            elements = new HashSet<>();
143            addAll(elements, a);
144            addAll(elements, b);
145            // the resulting list must contain at least each unique element, but may grow
146            newList = new ArrayList<>(elements.size());
147        }
148
149        @Override
150        public Iterator<O> iterator() {
151            return elements.iterator();
152        }
153
154        /**
155         * Add the object {@code count} times to the result collection.
156         * @param obj  the object to add
157         * @param count  the count
158         */
159        public void setCardinality(final O obj, final int count) {
160            for (int i = 0; i < count; i++) {
161                newList.add(obj);
162            }
163        }
164
165        /**
166         * Returns the resulting collection.
167         * @return the result
168         */
169        public Collection<O> list() {
170            return newList;
171        }
172
173    }
174
175    /**
176     * An empty unmodifiable collection.
177     * The JDK provides empty Set and List implementations which could be used for
178     * this purpose. However they could be cast to Set or List which might be
179     * undesirable. This implementation only implements Collection.
180     */
181    @SuppressWarnings("rawtypes") // we deliberately use the raw type here
182    public static final Collection EMPTY_COLLECTION = Collections.emptyList();
183
184    /**
185     * <code>CollectionUtils</code> should not normally be instantiated.
186     */
187    private CollectionUtils() {}
188
189    /**
190     * Returns the immutable EMPTY_COLLECTION with generic type safety.
191     *
192     * @see #EMPTY_COLLECTION
193     * @since 4.0
194     * @param <T> the element type
195     * @return immutable empty collection
196     */
197    @SuppressWarnings("unchecked") // OK, empty collection is compatible with any type
198    public static <T> Collection<T> emptyCollection() {
199        return EMPTY_COLLECTION;
200    }
201
202    /**
203     * Returns an immutable empty collection if the argument is <code>null</code>,
204     * or the argument itself otherwise.
205     *
206     * @param <T> the element type
207     * @param collection the collection, possibly <code>null</code>
208     * @return an empty collection if the argument is <code>null</code>
209     */
210    public static <T> Collection<T> emptyIfNull(final Collection<T> collection) {
211        return collection == null ? CollectionUtils.<T>emptyCollection() : collection;
212    }
213
214    /**
215     * Returns a {@link Collection} containing the union of the given
216     * {@link Iterable}s.
217     * <p>
218     * The cardinality of each element in the returned {@link Collection} will
219     * be equal to the maximum of the cardinality of that element in the two
220     * given {@link Iterable}s.
221     *
222     * @param a the first collection, must not be null
223     * @param b the second collection, must not be null
224     * @param <O> the generic type that is able to represent the types contained
225     *        in both input collections.
226     * @return the union of the two collections
227     * @see Collection#addAll
228     */
229    public static <O> Collection<O> union(final Iterable<? extends O> a, final Iterable<? extends O> b) {
230        final SetOperationCardinalityHelper<O> helper = new SetOperationCardinalityHelper<>(a, b);
231        for (final O obj : helper) {
232            helper.setCardinality(obj, helper.max(obj));
233        }
234        return helper.list();
235    }
236
237    /**
238     * Returns a {@link Collection} containing the intersection of the given
239     * {@link Iterable}s.
240     * <p>
241     * The cardinality of each element in the returned {@link Collection} will
242     * be equal to the minimum of the cardinality of that element in the two
243     * given {@link Iterable}s.
244     *
245     * @param a the first collection, must not be null
246     * @param b the second collection, must not be null
247     * @param <O> the generic type that is able to represent the types contained
248     *        in both input collections.
249     * @return the intersection of the two collections
250     * @see Collection#retainAll
251     * @see #containsAny
252     */
253    public static <O> Collection<O> intersection(final Iterable<? extends O> a, final Iterable<? extends O> b) {
254        final SetOperationCardinalityHelper<O> helper = new SetOperationCardinalityHelper<>(a, b);
255        for (final O obj : helper) {
256            helper.setCardinality(obj, helper.min(obj));
257        }
258        return helper.list();
259    }
260
261    /**
262     * Returns a {@link Collection} containing the exclusive disjunction
263     * (symmetric difference) of the given {@link Iterable}s.
264     * <p>
265     * The cardinality of each element <i>e</i> in the returned
266     * {@link Collection} will be equal to
267     * <code>max(cardinality(<i>e</i>,<i>a</i>),cardinality(<i>e</i>,<i>b</i>)) - min(cardinality(<i>e</i>,<i>a</i>),
268     * cardinality(<i>e</i>,<i>b</i>))</code>.
269     * <p>
270     * This is equivalent to
271     * {@code {@link #subtract subtract}({@link #union union(a,b)},{@link #intersection intersection(a,b)})}
272     * or
273     * {@code {@link #union union}({@link #subtract subtract(a,b)},{@link #subtract subtract(b,a)})}.
274
275     * @param a the first collection, must not be null
276     * @param b the second collection, must not be null
277     * @param <O> the generic type that is able to represent the types contained
278     *        in both input collections.
279     * @return the symmetric difference of the two collections
280     */
281    public static <O> Collection<O> disjunction(final Iterable<? extends O> a, final Iterable<? extends O> b) {
282        final SetOperationCardinalityHelper<O> helper = new SetOperationCardinalityHelper<>(a, b);
283        for (final O obj : helper) {
284            helper.setCardinality(obj, helper.max(obj) - helper.min(obj));
285        }
286        return helper.list();
287    }
288
289    /**
290     * Returns a new {@link Collection} containing {@code <i>a</i> - <i>b</i>}.
291     * The cardinality of each element <i>e</i> in the returned {@link Collection}
292     * will be the cardinality of <i>e</i> in <i>a</i> minus the cardinality
293     * of <i>e</i> in <i>b</i>, or zero, whichever is greater.
294     *
295     * @param a  the collection to subtract from, must not be null
296     * @param b  the collection to subtract, must not be null
297     * @param <O> the generic type that is able to represent the types contained
298     *        in both input collections.
299     * @return a new collection with the results
300     * @see Collection#removeAll
301     */
302    public static <O> Collection<O> subtract(final Iterable<? extends O> a, final Iterable<? extends O> b) {
303        final Predicate<O> p = TruePredicate.truePredicate();
304        return subtract(a, b, p);
305    }
306
307    /**
308     * Returns a new {@link Collection} containing <i>a</i> minus a subset of
309     * <i>b</i>.  Only the elements of <i>b</i> that satisfy the predicate
310     * condition, <i>p</i> are subtracted from <i>a</i>.
311     *
312     * <p>The cardinality of each element <i>e</i> in the returned {@link Collection}
313     * that satisfies the predicate condition will be the cardinality of <i>e</i> in <i>a</i>
314     * minus the cardinality of <i>e</i> in <i>b</i>, or zero, whichever is greater.</p>
315     * <p>The cardinality of each element <i>e</i> in the returned {@link Collection} that does <b>not</b>
316     * satisfy the predicate condition will be equal to the cardinality of <i>e</i> in <i>a</i>.</p>
317     *
318     * @param a  the collection to subtract from, must not be null
319     * @param b  the collection to subtract, must not be null
320     * @param p  the condition used to determine which elements of <i>b</i> are
321     *        subtracted.
322     * @param <O> the generic type that is able to represent the types contained
323     *        in both input collections.
324     * @return a new collection with the results
325     * @since 4.0
326     * @see Collection#removeAll
327     */
328    public static <O> Collection<O> subtract(final Iterable<? extends O> a,
329                                             final Iterable<? extends O> b,
330                                             final Predicate<O> p) {
331        final ArrayList<O> list = new ArrayList<>();
332        final HashBag<O> bag = new HashBag<>();
333        for (final O element : b) {
334            if (p.evaluate(element)) {
335                bag.add(element);
336            }
337        }
338        for (final O element : a) {
339            if (!bag.remove(element, 1)) {
340                list.add(element);
341            }
342        }
343        return list;
344    }
345
346    /**
347     * Returns <code>true</code> iff all elements of {@code coll2} are also contained
348     * in {@code coll1}. The cardinality of values in {@code coll2} is not taken into account,
349     * which is the same behavior as {@link Collection#containsAll(Collection)}.
350     * <p>
351     * In other words, this method returns <code>true</code> iff the
352     * {@link #intersection} of <i>coll1</i> and <i>coll2</i> has the same cardinality as
353     * the set of unique values from {@code coll2}. In case {@code coll2} is empty, {@code true}
354     * will be returned.
355     * <p>
356     * This method is intended as a replacement for {@link Collection#containsAll(Collection)}
357     * with a guaranteed runtime complexity of {@code O(n + m)}. Depending on the type of
358     * {@link Collection} provided, this method will be much faster than calling
359     * {@link Collection#containsAll(Collection)} instead, though this will come at the
360     * cost of an additional space complexity O(n).
361     *
362     * @param coll1  the first collection, must not be null
363     * @param coll2  the second collection, must not be null
364     * @return <code>true</code> iff the intersection of the collections has the same cardinality
365     *   as the set of unique elements from the second collection
366     * @since 4.0
367     */
368    public static boolean containsAll(final Collection<?> coll1, final Collection<?> coll2) {
369        if (coll2.isEmpty()) {
370            return true;
371        }
372        final Iterator<?> it = coll1.iterator();
373        final Set<Object> elementsAlreadySeen = new HashSet<>();
374        for (final Object nextElement : coll2) {
375            if (elementsAlreadySeen.contains(nextElement)) {
376                continue;
377            }
378
379            boolean foundCurrentElement = false;
380            while (it.hasNext()) {
381                final Object p = it.next();
382                elementsAlreadySeen.add(p);
383                if (nextElement == null ? p == null : nextElement.equals(p)) {
384                    foundCurrentElement = true;
385                    break;
386                }
387            }
388
389            if (!foundCurrentElement) {
390                return false;
391            }
392        }
393        return true;
394    }
395
396    /**
397     * Returns <code>true</code> iff at least one element is in both collections.
398     * <p>
399     * In other words, this method returns <code>true</code> iff the
400     * {@link #intersection} of <i>coll1</i> and <i>coll2</i> is not empty.
401     *
402     * @param <T> the type of object to lookup in <code>coll1</code>.
403     * @param coll1  the first collection, must not be null
404     * @param coll2  the second collection, must not be null
405     * @return <code>true</code> iff the intersection of the collections is non-empty
406     * @since 4.2
407     * @see #intersection
408     */
409    public static <T> boolean containsAny(final Collection<?> coll1, @SuppressWarnings("unchecked") final T... coll2) {
410        if (coll1.size() < coll2.length) {
411            for (final Object aColl1 : coll1) {
412                if (ArrayUtils.contains(coll2, aColl1)) {
413                    return true;
414                }
415            }
416        } else {
417            for (final Object aColl2 : coll2) {
418                if (coll1.contains(aColl2)) {
419                    return true;
420                }
421            }
422        }
423        return false;
424    }
425
426    /**
427     * Returns <code>true</code> iff at least one element is in both collections.
428     * <p>
429     * In other words, this method returns <code>true</code> iff the
430     * {@link #intersection} of <i>coll1</i> and <i>coll2</i> is not empty.
431     *
432     * @param coll1  the first collection, must not be null
433     * @param coll2  the second collection, must not be null
434     * @return <code>true</code> iff the intersection of the collections is non-empty
435     * @since 2.1
436     * @see #intersection
437     */
438    public static boolean containsAny(final Collection<?> coll1, final Collection<?> coll2) {
439        if (coll1.size() < coll2.size()) {
440            for (final Object aColl1 : coll1) {
441                if (coll2.contains(aColl1)) {
442                    return true;
443                }
444            }
445        } else {
446            for (final Object aColl2 : coll2) {
447                if (coll1.contains(aColl2)) {
448                    return true;
449                }
450            }
451        }
452        return false;
453    }
454
455    /**
456     * Returns a {@link Map} mapping each unique element in the given
457     * {@link Collection} to an {@link Integer} representing the number
458     * of occurrences of that element in the {@link Collection}.
459     * <p>
460     * Only those elements present in the collection will appear as
461     * keys in the map.
462     *
463     * @param <O>  the type of object in the returned {@link Map}. This is a super type of &lt;I&gt;.
464     * @param coll  the collection to get the cardinality map for, must not be null
465     * @return the populated cardinality map
466     */
467    public static <O> Map<O, Integer> getCardinalityMap(final Iterable<? extends O> coll) {
468        final Map<O, Integer> count = new HashMap<>();
469        for (final O obj : coll) {
470            final Integer c = count.get(obj);
471            if (c == null) {
472                count.put(obj, Integer.valueOf(1));
473            } else {
474                count.put(obj, Integer.valueOf(c.intValue() + 1));
475            }
476        }
477        return count;
478    }
479
480    /**
481     * Returns {@code true} iff <i>a</i> is a sub-collection of <i>b</i>,
482     * that is, iff the cardinality of <i>e</i> in <i>a</i> is less than or
483     * equal to the cardinality of <i>e</i> in <i>b</i>, for each element <i>e</i>
484     * in <i>a</i>.
485     *
486     * @param a the first (sub?) collection, must not be null
487     * @param b the second (super?) collection, must not be null
488     * @return <code>true</code> iff <i>a</i> is a sub-collection of <i>b</i>
489     * @see #isProperSubCollection
490     * @see Collection#containsAll
491     */
492    public static boolean isSubCollection(final Collection<?> a, final Collection<?> b) {
493        final CardinalityHelper<Object> helper = new CardinalityHelper<>(a, b);
494        for (final Object obj : a) {
495            if (helper.freqA(obj) > helper.freqB(obj)) {
496                return false;
497            }
498        }
499        return true;
500    }
501
502    /**
503     * Returns {@code true} iff <i>a</i> is a <i>proper</i> sub-collection of <i>b</i>,
504     * that is, iff the cardinality of <i>e</i> in <i>a</i> is less
505     * than or equal to the cardinality of <i>e</i> in <i>b</i>,
506     * for each element <i>e</i> in <i>a</i>, and there is at least one
507     * element <i>f</i> such that the cardinality of <i>f</i> in <i>b</i>
508     * is strictly greater than the cardinality of <i>f</i> in <i>a</i>.
509     * <p>
510     * The implementation assumes
511     * <ul>
512     *    <li><code>a.size()</code> and <code>b.size()</code> represent the
513     *    total cardinality of <i>a</i> and <i>b</i>, resp. </li>
514     *    <li><code>a.size() &lt; Integer.MAXVALUE</code></li>
515     * </ul>
516     *
517     * @param a  the first (sub?) collection, must not be null
518     * @param b  the second (super?) collection, must not be null
519     * @return <code>true</code> iff <i>a</i> is a <i>proper</i> sub-collection of <i>b</i>
520     * @see #isSubCollection
521     * @see Collection#containsAll
522     */
523    public static boolean isProperSubCollection(final Collection<?> a, final Collection<?> b) {
524        return a.size() < b.size() && CollectionUtils.isSubCollection(a, b);
525    }
526
527    /**
528     * Returns {@code true} iff the given {@link Collection}s contain
529     * exactly the same elements with exactly the same cardinalities.
530     * <p>
531     * That is, iff the cardinality of <i>e</i> in <i>a</i> is
532     * equal to the cardinality of <i>e</i> in <i>b</i>,
533     * for each element <i>e</i> in <i>a</i> or <i>b</i>.
534     *
535     * @param a  the first collection, must not be null
536     * @param b  the second collection, must not be null
537     * @return <code>true</code> iff the collections contain the same elements with the same cardinalities.
538     */
539    public static boolean isEqualCollection(final Collection<?> a, final Collection<?> b) {
540        if(a.size() != b.size()) {
541            return false;
542        }
543        final CardinalityHelper<Object> helper = new CardinalityHelper<>(a, b);
544        if(helper.cardinalityA.size() != helper.cardinalityB.size()) {
545            return false;
546        }
547        for( final Object obj : helper.cardinalityA.keySet()) {
548            if(helper.freqA(obj) != helper.freqB(obj)) {
549                return false;
550            }
551        }
552        return true;
553    }
554
555    /**
556     * Returns {@code true} iff the given {@link Collection}s contain
557     * exactly the same elements with exactly the same cardinalities.
558     * <p>
559     * That is, iff the cardinality of <i>e</i> in <i>a</i> is
560     * equal to the cardinality of <i>e</i> in <i>b</i>,
561     * for each element <i>e</i> in <i>a</i> or <i>b</i>.
562     * <p>
563     * <b>Note:</b> from version 4.1 onwards this method requires the input
564     * collections and equator to be of compatible type (using bounded wildcards).
565     * Providing incompatible arguments (e.g. by casting to their rawtypes)
566     * will result in a {@code ClassCastException} thrown at runtime.
567     *
568     * @param <E>  the element type
569     * @param a  the first collection, must not be null
570     * @param b  the second collection, must not be null
571     * @param equator  the Equator used for testing equality
572     * @return <code>true</code> iff the collections contain the same elements with the same cardinalities.
573     * @throws NullPointerException if the equator is null
574     * @since 4.0
575     */
576    public static <E> boolean isEqualCollection(final Collection<? extends E> a,
577                                                final Collection<? extends E> b,
578                                                final Equator<? super E> equator) {
579        if (equator == null) {
580            throw new NullPointerException("Equator must not be null.");
581        }
582
583        if(a.size() != b.size()) {
584            return false;
585        }
586
587        @SuppressWarnings({ "unchecked", "rawtypes" })
588        final Transformer<E, ?> transformer = new Transformer() {
589            @Override
590            public EquatorWrapper<?> transform(final Object input) {
591                return new EquatorWrapper(equator, input);
592            }
593        };
594
595        return isEqualCollection(collect(a, transformer), collect(b, transformer));
596    }
597
598    /**
599     * Wraps another object and uses the provided Equator to implement
600     * {@link #equals(Object)} and {@link #hashCode()}.
601     * <p>
602     * This class can be used to store objects into a Map.
603     *
604     * @param <O>  the element type
605     * @since 4.0
606     */
607    private static class EquatorWrapper<O> {
608        private final Equator<? super O> equator;
609        private final O object;
610
611        public EquatorWrapper(final Equator<? super O> equator, final O object) {
612            this.equator = equator;
613            this.object = object;
614        }
615
616        public O getObject() {
617            return object;
618        }
619
620        @Override
621        public boolean equals(final Object obj) {
622            if (!(obj instanceof EquatorWrapper)) {
623                return false;
624            }
625            @SuppressWarnings("unchecked")
626            final EquatorWrapper<O> otherObj = (EquatorWrapper<O>) obj;
627            return equator.equate(object, otherObj.getObject());
628        }
629
630        @Override
631        public int hashCode() {
632            return equator.hash(object);
633        }
634    }
635
636    /**
637     * Returns the number of occurrences of <i>obj</i> in <i>coll</i>.
638     *
639     * @param obj the object to find the cardinality of
640     * @param coll the {@link Iterable} to search
641     * @param <O> the type of object that the {@link Iterable} may contain.
642     * @return the number of occurrences of obj in coll
643     * @throws NullPointerException if coll is null
644     * @deprecated since 4.1, use {@link IterableUtils#frequency(Iterable, Object)} instead.
645     *   Be aware that the order of parameters has changed.
646     */
647    @Deprecated
648    public static <O> int cardinality(final O obj, final Iterable<? super O> coll) {
649        if (coll == null) {
650            throw new NullPointerException("coll must not be null.");
651        }
652        return IterableUtils.frequency(coll, obj);
653    }
654
655    /**
656     * Finds the first element in the given collection which matches the given predicate.
657     * <p>
658     * If the input collection or predicate is null, or no element of the collection
659     * matches the predicate, null is returned.
660     *
661     * @param <T>  the type of object the {@link Iterable} contains
662     * @param collection  the collection to search, may be null
663     * @param predicate  the predicate to use, may be null
664     * @return the first element of the collection which matches the predicate or null if none could be found
665     * @deprecated since 4.1, use {@link IterableUtils#find(Iterable, Predicate)} instead
666     */
667    @Deprecated
668    public static <T> T find(final Iterable<T> collection, final Predicate<? super T> predicate) {
669        return predicate != null ? IterableUtils.find(collection, predicate) : null;
670    }
671
672    /**
673     * Executes the given closure on each element in the collection.
674     * <p>
675     * If the input collection or closure is null, there is no change made.
676     *
677     * @param <T>  the type of object the {@link Iterable} contains
678     * @param <C>  the closure type
679     * @param collection  the collection to get the input from, may be null
680     * @param closure  the closure to perform, may be null
681     * @return closure
682     * @deprecated since 4.1, use {@link IterableUtils#forEach(Iterable, Closure)} instead
683     */
684    @Deprecated
685    public static <T, C extends Closure<? super T>> C forAllDo(final Iterable<T> collection, final C closure) {
686        if (closure != null) {
687            IterableUtils.forEach(collection, closure);
688        }
689        return closure;
690    }
691
692    /**
693     * Executes the given closure on each element in the collection.
694     * <p>
695     * If the input collection or closure is null, there is no change made.
696     *
697     * @param <T>  the type of object the {@link Iterator} contains
698     * @param <C>  the closure type
699     * @param iterator  the iterator to get the input from, may be null
700     * @param closure  the closure to perform, may be null
701     * @return closure
702     * @since 4.0
703     * @deprecated since 4.1, use {@link IteratorUtils#forEach(Iterator, Closure)} instead
704     */
705    @Deprecated
706    public static <T, C extends Closure<? super T>> C forAllDo(final Iterator<T> iterator, final C closure) {
707        if (closure != null) {
708            IteratorUtils.forEach(iterator, closure);
709        }
710        return closure;
711    }
712
713    /**
714     * Executes the given closure on each but the last element in the collection.
715     * <p>
716     * If the input collection or closure is null, there is no change made.
717     *
718     * @param <T>  the type of object the {@link Iterable} contains
719     * @param <C>  the closure type
720     * @param collection  the collection to get the input from, may be null
721     * @param closure  the closure to perform, may be null
722     * @return the last element in the collection, or null if either collection or closure is null
723     * @since 4.0
724     * @deprecated since 4.1, use {@link IterableUtils#forEachButLast(Iterable, Closure)} instead
725     */
726    @Deprecated
727    public static <T, C extends Closure<? super T>> T forAllButLastDo(final Iterable<T> collection,
728                                                                      final C closure) {
729        return closure != null ? IterableUtils.forEachButLast(collection, closure) : null;
730    }
731
732    /**
733     * Executes the given closure on each but the last element in the collection.
734     * <p>
735     * If the input collection or closure is null, there is no change made.
736     *
737     * @param <T>  the type of object the {@link Collection} contains
738     * @param <C>  the closure type
739     * @param iterator  the iterator to get the input from, may be null
740     * @param closure  the closure to perform, may be null
741     * @return the last element in the collection, or null if either iterator or closure is null
742     * @since 4.0
743     * @deprecated since 4.1, use {@link IteratorUtils#forEachButLast(Iterator, Closure)} instead
744     */
745    @Deprecated
746    public static <T, C extends Closure<? super T>> T forAllButLastDo(final Iterator<T> iterator, final C closure) {
747        return closure != null ? IteratorUtils.forEachButLast(iterator, closure) : null;
748    }
749
750    /**
751     * Filter the collection by applying a Predicate to each element. If the
752     * predicate returns false, remove the element.
753     * <p>
754     * If the input collection or predicate is null, there is no change made.
755     *
756     * @param <T>  the type of object the {@link Iterable} contains
757     * @param collection  the collection to get the input from, may be null
758     * @param predicate  the predicate to use as a filter, may be null
759     * @return true if the collection is modified by this call, false otherwise.
760     */
761    public static <T> boolean filter(final Iterable<T> collection, final Predicate<? super T> predicate) {
762        boolean result = false;
763        if (collection != null && predicate != null) {
764            for (final Iterator<T> it = collection.iterator(); it.hasNext();) {
765                if (!predicate.evaluate(it.next())) {
766                    it.remove();
767                    result = true;
768                }
769            }
770        }
771        return result;
772    }
773
774    /**
775     * Filter the collection by applying a Predicate to each element. If the
776     * predicate returns true, remove the element.
777     * <p>
778     * This is equivalent to <pre>filter(collection, PredicateUtils.notPredicate(predicate))</pre>
779     * if predicate is != null.
780     * <p>
781     * If the input collection or predicate is null, there is no change made.
782     *
783     * @param <T>  the type of object the {@link Iterable} contains
784     * @param collection  the collection to get the input from, may be null
785     * @param predicate  the predicate to use as a filter, may be null
786     * @return true if the collection is modified by this call, false otherwise.
787     */
788    public static <T> boolean filterInverse(final Iterable<T> collection, final Predicate<? super T> predicate) {
789        return filter(collection, predicate == null ? null : PredicateUtils.notPredicate(predicate));
790    }
791
792    /**
793     * Transform the collection by applying a Transformer to each element.
794     * <p>
795     * If the input collection or transformer is null, there is no change made.
796     * <p>
797     * This routine is best for Lists, for which set() is used to do the
798     * transformations "in place." For other Collections, clear() and addAll()
799     * are used to replace elements.
800     * <p>
801     * If the input collection controls its input, such as a Set, and the
802     * Transformer creates duplicates (or are otherwise invalid), the collection
803     * may reduce in size due to calling this method.
804     *
805     * @param <C>  the type of object the {@link Collection} contains
806     * @param collection  the {@link Collection} to get the input from, may be null
807     * @param transformer  the transformer to perform, may be null
808     */
809    public static <C> void transform(final Collection<C> collection,
810                                     final Transformer<? super C, ? extends C> transformer) {
811
812        if (collection != null && transformer != null) {
813            if (collection instanceof List<?>) {
814                final List<C> list = (List<C>) collection;
815                for (final ListIterator<C> it = list.listIterator(); it.hasNext();) {
816                    it.set(transformer.transform(it.next()));
817                }
818            } else {
819                final Collection<C> resultCollection = collect(collection, transformer);
820                collection.clear();
821                collection.addAll(resultCollection);
822            }
823        }
824    }
825
826    /**
827     * Counts the number of elements in the input collection that match the
828     * predicate.
829     * <p>
830     * A <code>null</code> collection or predicate matches no elements.
831     *
832     * @param <C>  the type of object the {@link Iterable} contains
833     * @param input  the {@link Iterable} to get the input from, may be null
834     * @param predicate  the predicate to use, may be null
835     * @return the number of matches for the predicate in the collection
836     * @deprecated since 4.1, use {@link IterableUtils#countMatches(Iterable, Predicate)} instead
837     */
838    @Deprecated
839    public static <C> int countMatches(final Iterable<C> input, final Predicate<? super C> predicate) {
840        return predicate == null ? 0 : (int) IterableUtils.countMatches(input, predicate);
841    }
842
843    /**
844     * Answers true if a predicate is true for at least one element of a
845     * collection.
846     * <p>
847     * A <code>null</code> collection or predicate returns false.
848     *
849     * @param <C>  the type of object the {@link Iterable} contains
850     * @param input  the {@link Iterable} to get the input from, may be null
851     * @param predicate  the predicate to use, may be null
852     * @return true if at least one element of the collection matches the predicate
853     * @deprecated since 4.1, use {@link IterableUtils#matchesAny(Iterable, Predicate)} instead
854     */
855    @Deprecated
856    public static <C> boolean exists(final Iterable<C> input, final Predicate<? super C> predicate) {
857        return predicate != null && IterableUtils.matchesAny(input, predicate);
858    }
859
860    /**
861     * Answers true if a predicate is true for every element of a
862     * collection.
863     * <p>
864     * A <code>null</code> predicate returns false.<br>
865     * A <code>null</code> or empty collection returns true.
866     *
867     * @param <C>  the type of object the {@link Iterable} contains
868     * @param input  the {@link Iterable} to get the input from, may be null
869     * @param predicate  the predicate to use, may be null
870     * @return true if every element of the collection matches the predicate or if the
871     * collection is empty, false otherwise
872     * @since 4.0
873     * @deprecated since 4.1, use {@link IterableUtils#matchesAll(Iterable, Predicate)} instead
874     */
875    @Deprecated
876    public static <C> boolean matchesAll(final Iterable<C> input, final Predicate<? super C> predicate) {
877        return predicate != null && IterableUtils.matchesAll(input, predicate);
878    }
879
880    /**
881     * Selects all elements from input collection which match the given
882     * predicate into an output collection.
883     * <p>
884     * A <code>null</code> predicate matches no elements.
885     *
886     * @param <O>  the type of object the {@link Iterable} contains
887     * @param inputCollection  the collection to get the input from, may not be null
888     * @param predicate  the predicate to use, may be null
889     * @return the elements matching the predicate (new list)
890     * @throws NullPointerException if the input collection is null
891     */
892    public static <O> Collection<O> select(final Iterable<? extends O> inputCollection,
893                                           final Predicate<? super O> predicate) {
894        final Collection<O> answer = inputCollection instanceof Collection<?> ?
895                new ArrayList<O>(((Collection<?>) inputCollection).size()) : new ArrayList<O>();
896        return select(inputCollection, predicate, answer);
897    }
898
899    /**
900     * Selects all elements from input collection which match the given
901     * predicate and adds them to outputCollection.
902     * <p>
903     * If the input collection or predicate is null, there is no change to the
904     * output collection.
905     *
906     * @param <O>  the type of object the {@link Iterable} contains
907     * @param <R>  the type of the output {@link Collection}
908     * @param inputCollection  the collection to get the input from, may be null
909     * @param predicate  the predicate to use, may be null
910     * @param outputCollection  the collection to output into, may not be null if the inputCollection
911     *   and predicate or not null
912     * @return the outputCollection
913     */
914    public static <O, R extends Collection<? super O>> R select(final Iterable<? extends O> inputCollection,
915            final Predicate<? super O> predicate, final R outputCollection) {
916
917        if (inputCollection != null && predicate != null) {
918            for (final O item : inputCollection) {
919                if (predicate.evaluate(item)) {
920                    outputCollection.add(item);
921                }
922            }
923        }
924        return outputCollection;
925    }
926
927    /**
928     * Selects all elements from inputCollection into an output and rejected collection,
929     * based on the evaluation of the given predicate.
930     * <p>
931     * Elements matching the predicate are added to the <code>outputCollection</code>,
932     * all other elements are added to the <code>rejectedCollection</code>.
933     * <p>
934     * If the input predicate is <code>null</code>, no elements are added to
935     * <code>outputCollection</code> or <code>rejectedCollection</code>.
936     * <p>
937     * Note: calling the method is equivalent to the following code snippet:
938     * <pre>
939     *   select(inputCollection, predicate, outputCollection);
940     *   selectRejected(inputCollection, predicate, rejectedCollection);
941     * </pre>
942     *
943     * @param <O>  the type of object the {@link Iterable} contains
944     * @param <R>  the type of the output {@link Collection}
945     * @param inputCollection  the collection to get the input from, may be null
946     * @param predicate  the predicate to use, may be null
947     * @param outputCollection  the collection to output selected elements into, may not be null if the
948     *   inputCollection and predicate are not null
949     * @param rejectedCollection  the collection to output rejected elements into, may not be null if the
950     *   inputCollection or predicate are not null
951     * @return the outputCollection
952     * @since 4.1
953     */
954    public static <O, R extends Collection<? super O>> R select(final Iterable<? extends O> inputCollection,
955            final Predicate<? super O> predicate, final R outputCollection, final R rejectedCollection) {
956
957        if (inputCollection != null && predicate != null) {
958            for (final O element : inputCollection) {
959                if (predicate.evaluate(element)) {
960                    outputCollection.add(element);
961                } else {
962                    rejectedCollection.add(element);
963                }
964            }
965        }
966        return outputCollection;
967    }
968
969    /**
970     * Selects all elements from inputCollection which don't match the given
971     * predicate into an output collection.
972     * <p>
973     * If the input predicate is <code>null</code>, the result is an empty
974     * list.
975     *
976     * @param <O>  the type of object the {@link Iterable} contains
977     * @param inputCollection  the collection to get the input from, may not be null
978     * @param predicate  the predicate to use, may be null
979     * @return the elements <b>not</b> matching the predicate (new list)
980     * @throws NullPointerException if the input collection is null
981     */
982    public static <O> Collection<O> selectRejected(final Iterable<? extends O> inputCollection,
983                                                   final Predicate<? super O> predicate) {
984        final Collection<O> answer = inputCollection instanceof Collection<?> ?
985                new ArrayList<O>(((Collection<?>) inputCollection).size()) : new ArrayList<O>();
986        return selectRejected(inputCollection, predicate, answer);
987    }
988
989    /**
990     * Selects all elements from inputCollection which don't match the given
991     * predicate and adds them to outputCollection.
992     * <p>
993     * If the input predicate is <code>null</code>, no elements are added to
994     * <code>outputCollection</code>.
995     *
996     * @param <O>  the type of object the {@link Iterable} contains
997     * @param <R>  the type of the output {@link Collection}
998     * @param inputCollection  the collection to get the input from, may be null
999     * @param predicate  the predicate to use, may be null
1000     * @param outputCollection  the collection to output into, may not be null if the inputCollection
1001     *   and predicate or not null
1002     * @return outputCollection
1003     */
1004    public static <O, R extends Collection<? super O>> R selectRejected(final Iterable<? extends O> inputCollection,
1005            final Predicate<? super O> predicate, final R outputCollection) {
1006
1007        if (inputCollection != null && predicate != null) {
1008            for (final O item : inputCollection) {
1009                if (!predicate.evaluate(item)) {
1010                    outputCollection.add(item);
1011                }
1012            }
1013        }
1014        return outputCollection;
1015    }
1016
1017    /**
1018     * Returns a new Collection containing all elements of the input collection
1019     * transformed by the given transformer.
1020     * <p>
1021     * If the input collection or transformer is null, the result is an empty list.
1022     *
1023     * @param <I>  the type of object in the input collection
1024     * @param <O>  the type of object in the output collection
1025     * @param inputCollection  the collection to get the input from, may not be null
1026     * @param transformer  the transformer to use, may be null
1027     * @return the transformed result (new list)
1028     * @throws NullPointerException if the input collection is null
1029     */
1030    public static <I, O> Collection<O> collect(final Iterable<I> inputCollection,
1031                                               final Transformer<? super I, ? extends O> transformer) {
1032        final Collection<O> answer = inputCollection instanceof Collection<?> ?
1033                new ArrayList<O>(((Collection<?>) inputCollection).size()) : new ArrayList<O>();
1034        return collect(inputCollection, transformer, answer);
1035    }
1036
1037    /**
1038     * Transforms all elements from the input iterator with the given transformer
1039     * and adds them to the output collection.
1040     * <p>
1041     * If the input iterator or transformer is null, the result is an empty list.
1042     *
1043     * @param <I>  the type of object in the input collection
1044     * @param <O>  the type of object in the output collection
1045     * @param inputIterator  the iterator to get the input from, may be null
1046     * @param transformer  the transformer to use, may be null
1047     * @return the transformed result (new list)
1048     */
1049    public static <I, O> Collection<O> collect(final Iterator<I> inputIterator,
1050                                               final Transformer<? super I, ? extends O> transformer) {
1051        return collect(inputIterator, transformer, new ArrayList<O>());
1052    }
1053
1054    /**
1055     * Transforms all elements from input collection with the given transformer
1056     * and adds them to the output collection.
1057     * <p>
1058     * If the input collection or transformer is null, there is no change to the
1059     * output collection.
1060     *
1061     * @param <I>  the type of object in the input collection
1062     * @param <O>  the type of object in the output collection
1063     * @param <R>  the type of the output collection
1064     * @param inputCollection  the collection to get the input from, may be null
1065     * @param transformer  the transformer to use, may be null
1066     * @param outputCollection  the collection to output into, may not be null if inputCollection
1067     *   and transformer are not null
1068     * @return the output collection with the transformed input added
1069     * @throws NullPointerException if the outputCollection is null and both, inputCollection and
1070     *   transformer are not null
1071     */
1072    public static <I, O, R extends Collection<? super O>> R collect(final Iterable<? extends I> inputCollection,
1073            final Transformer<? super I, ? extends O> transformer, final R outputCollection) {
1074        if (inputCollection != null) {
1075            return collect(inputCollection.iterator(), transformer, outputCollection);
1076        }
1077        return outputCollection;
1078    }
1079
1080    /**
1081     * Transforms all elements from the input iterator with the given transformer
1082     * and adds them to the output collection.
1083     * <p>
1084     * If the input iterator or transformer is null, there is no change to the
1085     * output collection.
1086     *
1087     * @param <I>  the type of object in the input collection
1088     * @param <O>  the type of object in the output collection
1089     * @param <R>  the type of the output collection
1090     * @param inputIterator  the iterator to get the input from, may be null
1091     * @param transformer  the transformer to use, may be null
1092     * @param outputCollection  the collection to output into, may not be null if inputIterator
1093     *   and transformer are not null
1094     * @return the outputCollection with the transformed input added
1095     * @throws NullPointerException if the output collection is null and both, inputIterator and
1096     *   transformer are not null
1097     */
1098    public static <I, O, R extends Collection<? super O>> R collect(final Iterator<? extends I> inputIterator,
1099            final Transformer<? super I, ? extends O> transformer, final R outputCollection) {
1100        if (inputIterator != null && transformer != null) {
1101            while (inputIterator.hasNext()) {
1102                final I item = inputIterator.next();
1103                final O value = transformer.transform(item);
1104                outputCollection.add(value);
1105            }
1106        }
1107        return outputCollection;
1108    }
1109
1110    //-----------------------------------------------------------------------
1111    /**
1112     * Adds an element to the collection unless the element is null.
1113     *
1114     * @param <T>  the type of object the {@link Collection} contains
1115     * @param collection  the collection to add to, must not be null
1116     * @param object  the object to add, if null it will not be added
1117     * @return true if the collection changed
1118     * @throws NullPointerException if the collection is null
1119     * @since 3.2
1120     */
1121    public static <T> boolean addIgnoreNull(final Collection<T> collection, final T object) {
1122        if (collection == null) {
1123            throw new NullPointerException("The collection must not be null");
1124        }
1125        return object != null && collection.add(object);
1126    }
1127
1128    /**
1129     * Adds all elements in the {@link Iterable} to the given collection. If the
1130     * {@link Iterable} is a {@link Collection} then it is cast and will be
1131     * added using {@link Collection#addAll(Collection)} instead of iterating.
1132     *
1133     * @param <C>  the type of object the {@link Collection} contains
1134     * @param collection  the collection to add to, must not be null
1135     * @param iterable  the iterable of elements to add, must not be null
1136     * @return a boolean indicating whether the collection has changed or not.
1137     * @throws NullPointerException if the collection or iterator is null
1138     */
1139    public static <C> boolean addAll(final Collection<C> collection, final Iterable<? extends C> iterable) {
1140        if (iterable instanceof Collection<?>) {
1141            return collection.addAll((Collection<? extends C>) iterable);
1142        }
1143        return addAll(collection, iterable.iterator());
1144    }
1145
1146    /**
1147     * Adds all elements in the iteration to the given collection.
1148     *
1149     * @param <C>  the type of object the {@link Collection} contains
1150     * @param collection  the collection to add to, must not be null
1151     * @param iterator  the iterator of elements to add, must not be null
1152     * @return a boolean indicating whether the collection has changed or not.
1153     * @throws NullPointerException if the collection or iterator is null
1154     */
1155    public static <C> boolean addAll(final Collection<C> collection, final Iterator<? extends C> iterator) {
1156        boolean changed = false;
1157        while (iterator.hasNext()) {
1158            changed |= collection.add(iterator.next());
1159        }
1160        return changed;
1161    }
1162
1163    /**
1164     * Adds all elements in the enumeration to the given collection.
1165     *
1166     * @param <C>  the type of object the {@link Collection} contains
1167     * @param collection  the collection to add to, must not be null
1168     * @param enumeration  the enumeration of elements to add, must not be null
1169     * @return {@code true} if the collections was changed, {@code false} otherwise
1170     * @throws NullPointerException if the collection or enumeration is null
1171     */
1172    public static <C> boolean addAll(final Collection<C> collection, final Enumeration<? extends C> enumeration) {
1173        boolean changed = false;
1174        while (enumeration.hasMoreElements()) {
1175            changed |= collection.add(enumeration.nextElement());
1176        }
1177        return changed;
1178    }
1179
1180    /**
1181     * Adds all elements in the array to the given collection.
1182     *
1183     * @param <C>  the type of object the {@link Collection} contains
1184     * @param collection  the collection to add to, must not be null
1185     * @param elements  the array of elements to add, must not be null
1186     * @return {@code true} if the collection was changed, {@code false} otherwise
1187     * @throws NullPointerException if the collection or array is null
1188     */
1189    public static <C> boolean addAll(final Collection<C> collection, final C... elements) {
1190        boolean changed = false;
1191        for (final C element : elements) {
1192            changed |= collection.add(element);
1193        }
1194        return changed;
1195    }
1196
1197    /**
1198     * Returns the <code>index</code>-th value in {@link Iterator}, throwing
1199     * <code>IndexOutOfBoundsException</code> if there is no such element.
1200     * <p>
1201     * The Iterator is advanced to <code>index</code> (or to the end, if
1202     * <code>index</code> exceeds the number of entries) as a side effect of this method.
1203     *
1204     * @param iterator  the iterator to get a value from
1205     * @param index  the index to get
1206     * @param <T> the type of object in the {@link Iterator}
1207     * @return the object at the specified index
1208     * @throws IndexOutOfBoundsException if the index is invalid
1209     * @throws IllegalArgumentException if the object type is invalid
1210     * @deprecated since 4.1, use {@code IteratorUtils.get(Iterator, int)} instead
1211     */
1212    @Deprecated
1213    public static <T> T get(final Iterator<T> iterator, final int index) {
1214        return IteratorUtils.get(iterator, index);
1215    }
1216
1217    /**
1218     * Ensures an index is not negative.
1219     * @param index the index to check.
1220     * @throws IndexOutOfBoundsException if the index is negative.
1221     */
1222    static void checkIndexBounds(final int index) {
1223        if (index < 0) {
1224            throw new IndexOutOfBoundsException("Index cannot be negative: " + index);
1225        }
1226    }
1227
1228    /**
1229     * Returns the <code>index</code>-th value in the <code>iterable</code>'s {@link Iterator}, throwing
1230     * <code>IndexOutOfBoundsException</code> if there is no such element.
1231     * <p>
1232     * If the {@link Iterable} is a {@link List}, then it will use {@link List#get(int)}.
1233     *
1234     * @param iterable  the {@link Iterable} to get a value from
1235     * @param index  the index to get
1236     * @param <T> the type of object in the {@link Iterable}.
1237     * @return the object at the specified index
1238     * @throws IndexOutOfBoundsException if the index is invalid
1239     * @deprecated since 4.1, use {@code IterableUtils.get(Iterable, int)} instead
1240     */
1241    @Deprecated
1242    public static <T> T get(final Iterable<T> iterable, final int index) {
1243        return IterableUtils.get(iterable, index);
1244    }
1245
1246    /**
1247     * Returns the <code>index</code>-th value in <code>object</code>, throwing
1248     * <code>IndexOutOfBoundsException</code> if there is no such element or
1249     * <code>IllegalArgumentException</code> if <code>object</code> is not an
1250     * instance of one of the supported types.
1251     * <p>
1252     * The supported types, and associated semantics are:
1253     * <ul>
1254     * <li> Map -- the value returned is the <code>Map.Entry</code> in position
1255     *      <code>index</code> in the map's <code>entrySet</code> iterator,
1256     *      if there is such an entry.</li>
1257     * <li> List -- this method is equivalent to the list's get method.</li>
1258     * <li> Array -- the <code>index</code>-th array entry is returned,
1259     *      if there is such an entry; otherwise an <code>IndexOutOfBoundsException</code>
1260     *      is thrown.</li>
1261     * <li> Collection -- the value returned is the <code>index</code>-th object
1262     *      returned by the collection's default iterator, if there is such an element.</li>
1263     * <li> Iterator or Enumeration -- the value returned is the
1264     *      <code>index</code>-th object in the Iterator/Enumeration, if there
1265     *      is such an element.  The Iterator/Enumeration is advanced to
1266     *      <code>index</code> (or to the end, if <code>index</code> exceeds the
1267     *      number of entries) as a side effect of this method.</li>
1268     * </ul>
1269     *
1270     * @param object  the object to get a value from
1271     * @param index  the index to get
1272     * @return the object at the specified index
1273     * @throws IndexOutOfBoundsException if the index is invalid
1274     * @throws IllegalArgumentException if the object type is invalid
1275     */
1276    public static Object get(final Object object, final int index) {
1277        final int i = index;
1278        if (i < 0) {
1279            throw new IndexOutOfBoundsException("Index cannot be negative: " + i);
1280        }
1281        if (object instanceof Map<?,?>) {
1282            final Map<?, ?> map = (Map<?, ?>) object;
1283            final Iterator<?> iterator = map.entrySet().iterator();
1284            return IteratorUtils.get(iterator, i);
1285        } else if (object instanceof Object[]) {
1286            return ((Object[]) object)[i];
1287        } else if (object instanceof Iterator<?>) {
1288            final Iterator<?> it = (Iterator<?>) object;
1289            return IteratorUtils.get(it, i);
1290        } else if (object instanceof Iterable<?>) {
1291            final Iterable<?> iterable = (Iterable<?>) object;
1292            return IterableUtils.get(iterable, i);
1293        } else if (object instanceof Enumeration<?>) {
1294            final Enumeration<?> it = (Enumeration<?>) object;
1295            return EnumerationUtils.get(it, i);
1296        } else if (object == null) {
1297            throw new IllegalArgumentException("Unsupported object type: null");
1298        } else {
1299            try {
1300                return Array.get(object, i);
1301            } catch (final IllegalArgumentException ex) {
1302                throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName());
1303            }
1304        }
1305    }
1306
1307    /**
1308     * Returns the <code>index</code>-th <code>Map.Entry</code> in the <code>map</code>'s <code>entrySet</code>,
1309     * throwing <code>IndexOutOfBoundsException</code> if there is no such element.
1310     *
1311     * @param <K>  the key type in the {@link Map}
1312     * @param <V>  the key type in the {@link Map}
1313     * @param map  the object to get a value from
1314     * @param index  the index to get
1315     * @return the object at the specified index
1316     * @throws IndexOutOfBoundsException if the index is invalid
1317     */
1318    public static <K,V> Map.Entry<K, V> get(final Map<K,V> map, final int index) {
1319        checkIndexBounds(index);
1320        return get(map.entrySet(), index);
1321    }
1322
1323    /**
1324     * Gets the size of the collection/iterator specified.
1325     * <p>
1326     * This method can handles objects as follows
1327     * <ul>
1328     * <li>Collection - the collection size
1329     * <li>Map - the map size
1330     * <li>Array - the array size
1331     * <li>Iterator - the number of elements remaining in the iterator
1332     * <li>Enumeration - the number of elements remaining in the enumeration
1333     * </ul>
1334     *
1335     * @param object  the object to get the size of, may be null
1336     * @return the size of the specified collection or 0 if the object was null
1337     * @throws IllegalArgumentException thrown if object is not recognized
1338     * @since 3.1
1339     */
1340    public static int size(final Object object) {
1341        if (object == null) {
1342            return 0;
1343        }
1344        int total = 0;
1345        if (object instanceof Map<?,?>) {
1346            total = ((Map<?, ?>) object).size();
1347        } else if (object instanceof Collection<?>) {
1348            total = ((Collection<?>) object).size();
1349        } else if (object instanceof Iterable<?>) {
1350            total = IterableUtils.size((Iterable<?>) object);
1351        } else if (object instanceof Object[]) {
1352            total = ((Object[]) object).length;
1353        } else if (object instanceof Iterator<?>) {
1354            total = IteratorUtils.size((Iterator<?>) object);
1355        } else if (object instanceof Enumeration<?>) {
1356            final Enumeration<?> it = (Enumeration<?>) object;
1357            while (it.hasMoreElements()) {
1358                total++;
1359                it.nextElement();
1360            }
1361        } else {
1362            try {
1363                total = Array.getLength(object);
1364            } catch (final IllegalArgumentException ex) {
1365                throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName());
1366            }
1367        }
1368        return total;
1369    }
1370
1371    /**
1372     * Checks if the specified collection/array/iterator is empty.
1373     * <p>
1374     * This method can handles objects as follows
1375     * <ul>
1376     * <li>Collection - via collection isEmpty
1377     * <li>Map - via map isEmpty
1378     * <li>Array - using array size
1379     * <li>Iterator - via hasNext
1380     * <li>Enumeration - via hasMoreElements
1381     * </ul>
1382     * <p>
1383     * Note: This method is named to avoid clashing with
1384     * {@link #isEmpty(Collection)}.
1385     *
1386     * @param object  the object to get the size of, may be null
1387     * @return true if empty or null
1388     * @throws IllegalArgumentException thrown if object is not recognized
1389     * @since 3.2
1390     */
1391    public static boolean sizeIsEmpty(final Object object) {
1392        if (object == null) {
1393            return true;
1394        } else if (object instanceof Collection<?>) {
1395            return ((Collection<?>) object).isEmpty();
1396        } else if (object instanceof Iterable<?>) {
1397            return IterableUtils.isEmpty((Iterable<?>) object);
1398        } else if (object instanceof Map<?, ?>) {
1399            return ((Map<?, ?>) object).isEmpty();
1400        } else if (object instanceof Object[]) {
1401            return ((Object[]) object).length == 0;
1402        } else if (object instanceof Iterator<?>) {
1403            return ((Iterator<?>) object).hasNext() == false;
1404        } else if (object instanceof Enumeration<?>) {
1405            return ((Enumeration<?>) object).hasMoreElements() == false;
1406        } else {
1407            try {
1408                return Array.getLength(object) == 0;
1409            } catch (final IllegalArgumentException ex) {
1410                throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName());
1411            }
1412        }
1413    }
1414
1415    //-----------------------------------------------------------------------
1416    /**
1417     * Null-safe check if the specified collection is empty.
1418     * <p>
1419     * Null returns true.
1420     *
1421     * @param coll  the collection to check, may be null
1422     * @return true if empty or null
1423     * @since 3.2
1424     */
1425    public static boolean isEmpty(final Collection<?> coll) {
1426        return coll == null || coll.isEmpty();
1427    }
1428
1429    /**
1430     * Null-safe check if the specified collection is not empty.
1431     * <p>
1432     * Null returns false.
1433     *
1434     * @param coll  the collection to check, may be null
1435     * @return true if non-null and non-empty
1436     * @since 3.2
1437     */
1438    public static boolean isNotEmpty(final Collection<?> coll) {
1439        return !isEmpty(coll);
1440    }
1441
1442    //-----------------------------------------------------------------------
1443    /**
1444     * Reverses the order of the given array.
1445     *
1446     * @param array  the array to reverse
1447     */
1448    public static void reverseArray(final Object[] array) {
1449        int i = 0;
1450        int j = array.length - 1;
1451        Object tmp;
1452
1453        while (j > i) {
1454            tmp = array[j];
1455            array[j] = array[i];
1456            array[i] = tmp;
1457            j--;
1458            i++;
1459        }
1460    }
1461
1462    /**
1463     * Returns true if no more elements can be added to the Collection.
1464     * <p>
1465     * This method uses the {@link BoundedCollection} interface to determine the
1466     * full status. If the collection does not implement this interface then
1467     * false is returned.
1468     * <p>
1469     * The collection does not have to implement this interface directly.
1470     * If the collection has been decorated using the decorators subpackage
1471     * then these will be removed to access the BoundedCollection.
1472     *
1473     * @param coll  the collection to check
1474     * @return true if the BoundedCollection is full
1475     * @throws NullPointerException if the collection is null
1476     */
1477    public static boolean isFull(final Collection<? extends Object> coll) {
1478        if (coll == null) {
1479            throw new NullPointerException("The collection must not be null");
1480        }
1481        if (coll instanceof BoundedCollection) {
1482            return ((BoundedCollection<?>) coll).isFull();
1483        }
1484        try {
1485            final BoundedCollection<?> bcoll =
1486                    UnmodifiableBoundedCollection.unmodifiableBoundedCollection(coll);
1487            return bcoll.isFull();
1488        } catch (final IllegalArgumentException ex) {
1489            return false;
1490        }
1491    }
1492
1493    /**
1494     * Get the maximum number of elements that the Collection can contain.
1495     * <p>
1496     * This method uses the {@link BoundedCollection} interface to determine the
1497     * maximum size. If the collection does not implement this interface then
1498     * -1 is returned.
1499     * <p>
1500     * The collection does not have to implement this interface directly.
1501     * If the collection has been decorated using the decorators subpackage
1502     * then these will be removed to access the BoundedCollection.
1503     *
1504     * @param coll  the collection to check
1505     * @return the maximum size of the BoundedCollection, -1 if no maximum size
1506     * @throws NullPointerException if the collection is null
1507     */
1508    public static int maxSize(final Collection<? extends Object> coll) {
1509        if (coll == null) {
1510            throw new NullPointerException("The collection must not be null");
1511        }
1512        if (coll instanceof BoundedCollection) {
1513            return ((BoundedCollection<?>) coll).maxSize();
1514        }
1515        try {
1516            final BoundedCollection<?> bcoll =
1517                    UnmodifiableBoundedCollection.unmodifiableBoundedCollection(coll);
1518            return bcoll.maxSize();
1519        } catch (final IllegalArgumentException ex) {
1520            return -1;
1521        }
1522    }
1523
1524    //-----------------------------------------------------------------------
1525    /**
1526     * Merges two sorted Collections, a and b, into a single, sorted List
1527     * such that the natural ordering of the elements is retained.
1528     * <p>
1529     * Uses the standard O(n) merge algorithm for combining two sorted lists.
1530     *
1531     * @param <O>  the element type
1532     * @param a  the first collection, must not be null
1533     * @param b  the second collection, must not be null
1534     * @return a new sorted List, containing the elements of Collection a and b
1535     * @throws NullPointerException if either collection is null
1536     * @since 4.0
1537     */
1538    public static <O extends Comparable<? super O>> List<O> collate(final Iterable<? extends O> a,
1539                                                                    final Iterable<? extends O> b) {
1540        return collate(a, b, ComparatorUtils.<O>naturalComparator(), true);
1541    }
1542
1543    /**
1544     * Merges two sorted Collections, a and b, into a single, sorted List
1545     * such that the natural ordering of the elements is retained.
1546     * <p>
1547     * Uses the standard O(n) merge algorithm for combining two sorted lists.
1548     *
1549     * @param <O>  the element type
1550     * @param a  the first collection, must not be null
1551     * @param b  the second collection, must not be null
1552     * @param includeDuplicates  if {@code true} duplicate elements will be retained, otherwise
1553     *   they will be removed in the output collection
1554     * @return a new sorted List, containing the elements of Collection a and b
1555     * @throws NullPointerException if either collection is null
1556     * @since 4.0
1557     */
1558    public static <O extends Comparable<? super O>> List<O> collate(final Iterable<? extends O> a,
1559                                                                    final Iterable<? extends O> b,
1560                                                                    final boolean includeDuplicates) {
1561        return collate(a, b, ComparatorUtils.<O>naturalComparator(), includeDuplicates);
1562    }
1563
1564    /**
1565     * Merges two sorted Collections, a and b, into a single, sorted List
1566     * such that the ordering of the elements according to Comparator c is retained.
1567     * <p>
1568     * Uses the standard O(n) merge algorithm for combining two sorted lists.
1569     *
1570     * @param <O>  the element type
1571     * @param a  the first collection, must not be null
1572     * @param b  the second collection, must not be null
1573     * @param c  the comparator to use for the merge.
1574     * @return a new sorted List, containing the elements of Collection a and b
1575     * @throws NullPointerException if either collection or the comparator is null
1576     * @since 4.0
1577     */
1578    public static <O> List<O> collate(final Iterable<? extends O> a, final Iterable<? extends O> b,
1579                                      final Comparator<? super O> c) {
1580        return collate(a, b, c, true);
1581    }
1582
1583    /**
1584     * Merges two sorted Collections, a and b, into a single, sorted List
1585     * such that the ordering of the elements according to Comparator c is retained.
1586     * <p>
1587     * Uses the standard O(n) merge algorithm for combining two sorted lists.
1588     *
1589     * @param <O>  the element type
1590     * @param a  the first collection, must not be null
1591     * @param b  the second collection, must not be null
1592     * @param c  the comparator to use for the merge.
1593     * @param includeDuplicates  if {@code true} duplicate elements will be retained, otherwise
1594     *   they will be removed in the output collection
1595     * @return a new sorted List, containing the elements of Collection a and b
1596     * @throws NullPointerException if either collection or the comparator is null
1597     * @since 4.0
1598     */
1599    public static <O> List<O> collate(final Iterable<? extends O> a, final Iterable<? extends O> b,
1600                                      final Comparator<? super O> c, final boolean includeDuplicates) {
1601
1602        if (a == null || b == null) {
1603            throw new NullPointerException("The collections must not be null");
1604        }
1605        if (c == null) {
1606            throw new NullPointerException("The comparator must not be null");
1607        }
1608
1609        // if both Iterables are a Collection, we can estimate the size
1610        final int totalSize = a instanceof Collection<?> && b instanceof Collection<?> ?
1611                Math.max(1, ((Collection<?>) a).size() + ((Collection<?>) b).size()) : 10;
1612
1613        final Iterator<O> iterator = new CollatingIterator<>(c, a.iterator(), b.iterator());
1614        if (includeDuplicates) {
1615            return IteratorUtils.toList(iterator, totalSize);
1616        }
1617        final ArrayList<O> mergedList = new ArrayList<>(totalSize);
1618
1619        O lastItem = null;
1620        while (iterator.hasNext()) {
1621            final O item = iterator.next();
1622            if (lastItem == null || !lastItem.equals(item)) {
1623                mergedList.add(item);
1624            }
1625            lastItem = item;
1626        }
1627
1628        mergedList.trimToSize();
1629        return mergedList;
1630    }
1631
1632    //-----------------------------------------------------------------------
1633
1634    /**
1635     * Returns a {@link Collection} of all the permutations of the input collection.
1636     * <p>
1637     * NOTE: the number of permutations of a given collection is equal to n!, where
1638     * n is the size of the collection. Thus, the resulting collection will become
1639     * <b>very</b> large for collections &gt; 10 (e.g. 10! = 3628800, 15! = 1307674368000).
1640     * <p>
1641     * For larger collections it is advised to use a {@link PermutationIterator} to
1642     * iterate over all permutations.
1643     *
1644     * @see PermutationIterator
1645     *
1646     * @param <E>  the element type
1647     * @param collection  the collection to create permutations for, may not be null
1648     * @return an unordered collection of all permutations of the input collection
1649     * @throws NullPointerException if collection is null
1650     * @since 4.0
1651     */
1652    public static <E> Collection<List<E>> permutations(final Collection<E> collection) {
1653        final PermutationIterator<E> it = new PermutationIterator<>(collection);
1654        final Collection<List<E>> result = new ArrayList<>();
1655        while (it.hasNext()) {
1656            result.add(it.next());
1657        }
1658        return result;
1659    }
1660
1661    //-----------------------------------------------------------------------
1662    /**
1663     * Returns a collection containing all the elements in <code>collection</code>
1664     * that are also in <code>retain</code>. The cardinality of an element <code>e</code>
1665     * in the returned collection is the same as the cardinality of <code>e</code>
1666     * in <code>collection</code> unless <code>retain</code> does not contain <code>e</code>, in which
1667     * case the cardinality is zero. This method is useful if you do not wish to modify
1668     * the collection <code>c</code> and thus cannot call <code>c.retainAll(retain);</code>.
1669     * <p>
1670     * This implementation iterates over <code>collection</code>, checking each element in
1671     * turn to see if it's contained in <code>retain</code>. If it's contained, it's added
1672     * to the returned list. As a consequence, it is advised to use a collection type for
1673     * <code>retain</code> that provides a fast (e.g. O(1)) implementation of
1674     * {@link Collection#contains(Object)}.
1675     *
1676     * @param <C>  the type of object the {@link Collection} contains
1677     * @param collection  the collection whose contents are the target of the #retailAll operation
1678     * @param retain  the collection containing the elements to be retained in the returned collection
1679     * @return a <code>Collection</code> containing all the elements of <code>collection</code>
1680     * that occur at least once in <code>retain</code>.
1681     * @throws NullPointerException if either parameter is null
1682     * @since 3.2
1683     */
1684    public static <C> Collection<C> retainAll(final Collection<C> collection, final Collection<?> retain) {
1685        return ListUtils.retainAll(collection, retain);
1686    }
1687
1688    /**
1689     * Returns a collection containing all the elements in
1690     * <code>collection</code> that are also in <code>retain</code>. The
1691     * cardinality of an element <code>e</code> in the returned collection is
1692     * the same as the cardinality of <code>e</code> in <code>collection</code>
1693     * unless <code>retain</code> does not contain <code>e</code>, in which case
1694     * the cardinality is zero. This method is useful if you do not wish to
1695     * modify the collection <code>c</code> and thus cannot call
1696     * <code>c.retainAll(retain);</code>.
1697     * <p>
1698     * Moreover this method uses an {@link Equator} instead of
1699     * {@link Object#equals(Object)} to determine the equality of the elements
1700     * in <code>collection</code> and <code>retain</code>. Hence this method is
1701     * useful in cases where the equals behavior of an object needs to be
1702     * modified without changing the object itself.
1703     *
1704     * @param <E> the type of object the {@link Collection} contains
1705     * @param collection the collection whose contents are the target of the {@code retainAll} operation
1706     * @param retain the collection containing the elements to be retained in the returned collection
1707     * @param equator the Equator used for testing equality
1708     * @return a <code>Collection</code> containing all the elements of <code>collection</code>
1709     * that occur at least once in <code>retain</code> according to the <code>equator</code>
1710     * @throws NullPointerException if any of the parameters is null
1711     * @since 4.1
1712     */
1713    public static <E> Collection<E> retainAll(final Iterable<E> collection,
1714                                              final Iterable<? extends E> retain,
1715                                              final Equator<? super E> equator) {
1716
1717        final Transformer<E, EquatorWrapper<E>> transformer = new Transformer<E, EquatorWrapper<E>>() {
1718            @Override
1719            public EquatorWrapper<E> transform(final E input) {
1720                return new EquatorWrapper<>(equator, input);
1721            }
1722        };
1723
1724        final Set<EquatorWrapper<E>> retainSet =
1725                collect(retain, transformer, new HashSet<EquatorWrapper<E>>());
1726
1727        final List<E> list = new ArrayList<>();
1728        for (final E element : collection) {
1729            if (retainSet.contains(new EquatorWrapper<>(equator, element))) {
1730                list.add(element);
1731            }
1732        }
1733        return list;
1734    }
1735
1736    /**
1737     * Removes the elements in <code>remove</code> from <code>collection</code>. That is, this
1738     * method returns a collection containing all the elements in <code>c</code>
1739     * that are not in <code>remove</code>. The cardinality of an element <code>e</code>
1740     * in the returned collection is the same as the cardinality of <code>e</code>
1741     * in <code>collection</code> unless <code>remove</code> contains <code>e</code>, in which
1742     * case the cardinality is zero. This method is useful if you do not wish to modify
1743     * the collection <code>c</code> and thus cannot call <code>collection.removeAll(remove);</code>.
1744     * <p>
1745     * This implementation iterates over <code>collection</code>, checking each element in
1746     * turn to see if it's contained in <code>remove</code>. If it's not contained, it's added
1747     * to the returned list. As a consequence, it is advised to use a collection type for
1748     * <code>remove</code> that provides a fast (e.g. O(1)) implementation of
1749     * {@link Collection#contains(Object)}.
1750     *
1751     * @param <E>  the type of object the {@link Collection} contains
1752     * @param collection  the collection from which items are removed (in the returned collection)
1753     * @param remove  the items to be removed from the returned <code>collection</code>
1754     * @return a <code>Collection</code> containing all the elements of <code>collection</code> except
1755     * any elements that also occur in <code>remove</code>.
1756     * @throws NullPointerException if either parameter is null
1757     * @since 4.0 (method existed in 3.2 but was completely broken)
1758     */
1759    public static <E> Collection<E> removeAll(final Collection<E> collection, final Collection<?> remove) {
1760        return ListUtils.removeAll(collection, remove);
1761  }
1762
1763    /**
1764     * Removes all elements in <code>remove</code> from <code>collection</code>.
1765     * That is, this method returns a collection containing all the elements in
1766     * <code>collection</code> that are not in <code>remove</code>. The
1767     * cardinality of an element <code>e</code> in the returned collection is
1768     * the same as the cardinality of <code>e</code> in <code>collection</code>
1769     * unless <code>remove</code> contains <code>e</code>, in which case the
1770     * cardinality is zero. This method is useful if you do not wish to modify
1771     * the collection <code>c</code> and thus cannot call
1772     * <code>collection.removeAll(remove)</code>.
1773     * <p>
1774     * Moreover this method uses an {@link Equator} instead of
1775     * {@link Object#equals(Object)} to determine the equality of the elements
1776     * in <code>collection</code> and <code>remove</code>. Hence this method is
1777     * useful in cases where the equals behavior of an object needs to be
1778     * modified without changing the object itself.
1779     *
1780     * @param <E> the type of object the {@link Collection} contains
1781     * @param collection the collection from which items are removed (in the returned collection)
1782     * @param remove the items to be removed from the returned collection
1783     * @param equator the Equator used for testing equality
1784     * @return a <code>Collection</code> containing all the elements of <code>collection</code>
1785     * except any element that if equal according to the <code>equator</code>
1786     * @throws NullPointerException if any of the parameters is null
1787     * @since 4.1
1788     */
1789    public static <E> Collection<E> removeAll(final Iterable<E> collection,
1790                                              final Iterable<? extends E> remove,
1791                                              final Equator<? super E> equator) {
1792
1793        final Transformer<E, EquatorWrapper<E>> transformer = new Transformer<E, EquatorWrapper<E>>() {
1794            @Override
1795            public EquatorWrapper<E> transform(final E input) {
1796                return new EquatorWrapper<>(equator, input);
1797            }
1798        };
1799
1800        final Set<EquatorWrapper<E>> removeSet =
1801                collect(remove, transformer, new HashSet<EquatorWrapper<E>>());
1802
1803        final List<E> list = new ArrayList<>();
1804        for (final E element : collection) {
1805            if (!removeSet.contains(new EquatorWrapper<>(equator, element))) {
1806                list.add(element);
1807            }
1808        }
1809        return list;
1810    }
1811
1812    //-----------------------------------------------------------------------
1813    /**
1814     * Returns a synchronized collection backed by the given collection.
1815     * <p>
1816     * You must manually synchronize on the returned buffer's iterator to
1817     * avoid non-deterministic behavior:
1818     *
1819     * <pre>
1820     * Collection c = CollectionUtils.synchronizedCollection(myCollection);
1821     * synchronized (c) {
1822     *     Iterator i = c.iterator();
1823     *     while (i.hasNext()) {
1824     *         process (i.next());
1825     *     }
1826     * }
1827     * </pre>
1828     *
1829     * This method uses the implementation in the decorators subpackage.
1830     *
1831     * @param <C>  the type of object the {@link Collection} contains
1832     * @param collection  the collection to synchronize, must not be null
1833     * @return a synchronized collection backed by the given collection
1834     * @throws NullPointerException if the collection is null
1835     * @deprecated since 4.1, use {@link java.util.Collections#synchronizedCollection(Collection)} instead
1836     */
1837    @Deprecated
1838    public static <C> Collection<C> synchronizedCollection(final Collection<C> collection) {
1839        return SynchronizedCollection.synchronizedCollection(collection);
1840    }
1841
1842    /**
1843     * Returns an unmodifiable collection backed by the given collection.
1844     * <p>
1845     * This method uses the implementation in the decorators subpackage.
1846     *
1847     * @param <C>  the type of object the {@link Collection} contains
1848     * @param collection  the collection to make unmodifiable, must not be null
1849     * @return an unmodifiable collection backed by the given collection
1850     * @throws NullPointerException if the collection is null
1851     * @deprecated since 4.1, use {@link java.util.Collections#unmodifiableCollection(Collection)} instead
1852     */
1853    @Deprecated
1854    public static <C> Collection<C> unmodifiableCollection(final Collection<? extends C> collection) {
1855        return UnmodifiableCollection.unmodifiableCollection(collection);
1856    }
1857
1858    /**
1859     * Returns a predicated (validating) collection backed by the given collection.
1860     * <p>
1861     * Only objects that pass the test in the given predicate can be added to the collection.
1862     * Trying to add an invalid object results in an IllegalArgumentException.
1863     * It is important not to use the original collection after invoking this method,
1864     * as it is a backdoor for adding invalid objects.
1865     *
1866     * @param <C> the type of objects in the Collection.
1867     * @param collection  the collection to predicate, must not be null
1868     * @param predicate  the predicate for the collection, must not be null
1869     * @return a predicated collection backed by the given collection
1870     * @throws NullPointerException if the Collection is null
1871     */
1872    public static <C> Collection<C> predicatedCollection(final Collection<C> collection,
1873                                                         final Predicate<? super C> predicate) {
1874        return PredicatedCollection.predicatedCollection(collection, predicate);
1875    }
1876
1877    /**
1878     * Returns a transformed bag backed by the given collection.
1879     * <p>
1880     * Each object is passed through the transformer as it is added to the
1881     * Collection. It is important not to use the original collection after invoking this
1882     * method, as it is a backdoor for adding untransformed objects.
1883     * <p>
1884     * Existing entries in the specified collection will not be transformed.
1885     * If you want that behaviour, see {@link TransformedCollection#transformedCollection}.
1886     *
1887     * @param <E> the type of object the {@link Collection} contains
1888     * @param collection  the collection to predicate, must not be null
1889     * @param transformer  the transformer for the collection, must not be null
1890     * @return a transformed collection backed by the given collection
1891     * @throws NullPointerException if the Collection or Transformer is null
1892     */
1893    public static <E> Collection<E> transformingCollection(final Collection<E> collection,
1894            final Transformer<? super E, ? extends E> transformer) {
1895        return TransformedCollection.transformingCollection(collection, transformer);
1896    }
1897
1898    /**
1899     * Extract the lone element of the specified Collection.
1900     * @param <E> collection type
1901     * @param collection to read
1902     * @return sole member of collection
1903     * @throws NullPointerException if collection is null
1904     * @throws IllegalArgumentException if collection is empty or contains more than one element
1905     * @since 4.0
1906     */
1907    public static <E> E extractSingleton(final Collection<E> collection) {
1908        if (collection == null) {
1909            throw new NullPointerException("Collection must not be null.");
1910        }
1911        if (collection.size() != 1) {
1912            throw new IllegalArgumentException("Can extract singleton only when collection size == 1");
1913        }
1914        return collection.iterator().next();
1915    }
1916}