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