Return-Path: Delivered-To: apmail-commons-commits-archive@minotaur.apache.org Received: (qmail 21057 invoked from network); 15 Sep 2009 05:55:46 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 15 Sep 2009 05:55:46 -0000 Received: (qmail 7327 invoked by uid 500); 15 Sep 2009 05:55:45 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 7255 invoked by uid 500); 15 Sep 2009 05:55:45 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 7215 invoked by uid 99); 15 Sep 2009 05:55:45 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 15 Sep 2009 05:55:45 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 15 Sep 2009 05:55:39 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 3C3A42388A29; Tue, 15 Sep 2009 05:54:55 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r815042 - /commons/proper/collections/trunk/src/java/org/apache/commons/collections/CollectionUtils.java Date: Tue, 15 Sep 2009 05:54:55 -0000 To: commits@commons.apache.org From: bayard@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090915055455.3C3A42388A29@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: bayard Date: Tue Sep 15 05:54:54 2009 New Revision: 815042 URL: http://svn.apache.org/viewvc?rev=815042&view=rev Log: Merging from -r468106:814127 of collections_jdk5_branch - namely where this code was generified; mostly in r738956. Also see the following revisions: ------------------------------------------------------------------------ r814063 | sebb | 2009-09-11 15:25:29 -0700 (Fri, 11 Sep 2009) | 1 line Javadoc typos; fix internal raw types ------------------------------------------------------------------------ r814050 | sebb | 2009-09-11 15:01:25 -0700 (Fri, 11 Sep 2009) | 1 line Some minor Javadoc fixes ------------------------------------------------------------------------ r813951 | mbenson | 2009-09-11 10:48:55 -0700 (Fri, 11 Sep 2009) | 1 line [COLLECTIONS-286] CollectionsUtils.extractSingleton ------------------------------------------------------------------------ r813925 | mbenson | 2009-09-11 10:05:31 -0700 (Fri, 11 Sep 2009) | 1 line [COLLECTIONS-182] return Closure from CollectionUtils.forAllDo ------------------------------------------------------------------------ r648113 | skestle | 2008-04-14 21:32:39 -0700 (Mon, 14 Apr 2008) | 1 line Updated CollectionUtils to return the same type of Collection that is passed into select(), reject() and collect() ------------------------------------------------------------------------ r593968 | skestle | 2007-11-11 13:59:08 -0800 (Sun, 11 Nov 2007) | 1 line Missed 1 variable rename causing test to fail for COLLECTIONS-245 ------------------------------------------------------------------------ r593964 | skestle | 2007-11-11 13:44:41 -0800 (Sun, 11 Nov 2007) | 2 lines Applied (most of) Brian Egge's clean up patch of previous commit for COLLECTIONS-245 - thanks! (And we're at 100%) ------------------------------------------------------------------------ r593144 | skestle | 2007-11-08 04:21:55 -0800 (Thu, 08 Nov 2007) | 3 lines Updated CollectionUtils and test. Probably 80-90% complete for generics. Very open to review / patches. Jira: COLLECTIONS-245 ------------------------------------------------------------------------ r562381 | skestle | 2007-08-03 01:15:35 -0700 (Fri, 03 Aug 2007) | 1 line Extracted private CollectionUtils.CardinalityHelper classes to allow easier generic refactoring/maintenance and code readability. ------------------------------------------------------------------------ r561846 | niallp | 2007-08-01 08:53:19 -0700 (Wed, 01 Aug 2007) | 1 line Test commit (just remove a trailing space) on Collections JDK5 Branch ------------------------------------------------------------------------ r471166 | scolebourne | 2006-11-04 03:33:22 -0800 (Sat, 04 Nov 2006) | 1 line Removed Typed* containers such as TypedList and TypedMap as generics now provides type safety ------------------------------------------------------------------------ r468690 | scolebourne | 2006-10-28 06:03:11 -0700 (Sat, 28 Oct 2006) | 1 line COLLECTIONS-229 - Remove deprecated classes and code ------------------------------------------------------------------------ Modified: commons/proper/collections/trunk/src/java/org/apache/commons/collections/CollectionUtils.java Modified: commons/proper/collections/trunk/src/java/org/apache/commons/collections/CollectionUtils.java URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/java/org/apache/commons/collections/CollectionUtils.java?rev=815042&r1=815041&r2=815042&view=diff ============================================================================== --- commons/proper/collections/trunk/src/java/org/apache/commons/collections/CollectionUtils.java (original) +++ commons/proper/collections/trunk/src/java/org/apache/commons/collections/CollectionUtils.java Tue Sep 15 05:54:54 2009 @@ -31,12 +31,12 @@ import org.apache.commons.collections.collection.PredicatedCollection; import org.apache.commons.collections.collection.SynchronizedCollection; import org.apache.commons.collections.collection.TransformedCollection; -import org.apache.commons.collections.collection.TypedCollection; import org.apache.commons.collections.collection.UnmodifiableBoundedCollection; import org.apache.commons.collections.collection.UnmodifiableCollection; /** * Provides utility methods and decorators for {@link Collection} instances. + * Method parameters will take {@link Iterable} objects when possible. * * @since Commons Collections 1.0 * @version $Revision$ $Date$ @@ -54,11 +54,72 @@ * @author Jon Schewe * @author Neil O'Toole * @author Stephen Smith + * @author Stephen Kestle */ +//TODO - note generic types for review in wiki - especially ones +//TODO - doc Cardinality Helpers public class CollectionUtils { - /** Constant to avoid repeated object creation */ - private static final Integer INTEGER_ONE = new Integer(1); + private static class CardinalityHelper { + final Map cardinalityA, cardinalityB; + + public CardinalityHelper(Iterable a, Iterable b) { + cardinalityA = CollectionUtils.getCardinalityMap(a); + cardinalityB = CollectionUtils.getCardinalityMap(b); + } + + public final int max(Object obj) { + return Math.max(freqA(obj), freqB(obj)); + } + + public final int min(Object obj) { + return Math.min(freqA(obj), freqB(obj)); + } + + public int freqA(Object obj) { + return getFreq(obj, cardinalityA); + } + + public int freqB(Object obj) { + return getFreq(obj, cardinalityB); + } + + private final int getFreq(final Object obj, final Map freqMap) { + Integer count = freqMap.get(obj); + if (count != null) { + return count; + } + return 0; + } + } + + private static class SetOperationCardinalityHelper extends CardinalityHelper implements Iterable { + private final Set elements; + private final List newList; + + public SetOperationCardinalityHelper(Iterable a, Iterable b) { + super(a, b); + elements = new HashSet(); + addAll(elements, a); + addAll(elements, b); + newList = new ArrayList(); + } + + public Iterator iterator() { + return elements.iterator(); + } + + public void setCardinality(O obj, int count) { + for (int i = 0; i < count; i++) { + newList.add(obj); + } + } + + public Collection list() { + return newList; + } + + } /** * An empty unmodifiable collection. @@ -66,7 +127,8 @@ * this purpose. However they could be cast to Set or List which might be * undesirable. This implementation only implements Collection. */ - public static final Collection EMPTY_COLLECTION = UnmodifiableCollection.decorate(new ArrayList()); + @SuppressWarnings("unchecked") + public static final Collection EMPTY_COLLECTION = UnmodifiableCollection.decorate(new ArrayList()); /** * CollectionUtils should not normally be instantiated. @@ -75,95 +137,89 @@ } /** - * Returns a {@link Collection} containing the union - * of the given {@link Collection}s. + * Returns the immutable EMPTY_COLLECTION with generic type safety. + * + * @see #EMPTY_COLLECTION + * @since 4.0 + * @return immutable empty collection + */ + @SuppressWarnings("unchecked") + public static Collection emptyCollection() { + return EMPTY_COLLECTION; + } + + /** + * Returns a {@link Collection} containing the union of the given + * {@link Collection}s. *

- * The cardinality of each element in the returned {@link Collection} - * will be equal to the maximum of the cardinality of that element - * in the two given {@link Collection}s. + * The cardinality of each element in the returned {@link Collection} will + * be equal to the maximum of the cardinality of that element in the two + * given {@link Collection}s. * - * @param a the first collection, must not be null - * @param b the second collection, must not be null - * @return the union of the two collections + * @param a the first collection, must not be null + * @param b the second collection, must not be null + * @param the generic type that is able to represent the types contained + * in both input collections. + * @return the union of the two collections * @see Collection#addAll */ - public static Collection union(final Collection a, final Collection b) { - ArrayList list = new ArrayList(); - Map mapa = getCardinalityMap(a); - Map mapb = getCardinalityMap(b); - Set elts = new HashSet(a); - elts.addAll(b); - Iterator it = elts.iterator(); - while(it.hasNext()) { - Object obj = it.next(); - for(int i=0,m=Math.max(getFreq(obj,mapa),getFreq(obj,mapb));i Collection union(final Iterable a, final Iterable b) { + SetOperationCardinalityHelper helper = new SetOperationCardinalityHelper(a, b); + for (O obj : helper) { + helper.setCardinality(obj, helper.max(obj)); } - return list; + return helper.list(); } /** - * Returns a {@link Collection} containing the intersection - * of the given {@link Collection}s. + * Returns a {@link Collection} containing the intersection of the given + * {@link Collection}s. *

- * The cardinality of each element in the returned {@link Collection} - * will be equal to the minimum of the cardinality of that element - * in the two given {@link Collection}s. + * The cardinality of each element in the returned {@link Collection} will + * be equal to the minimum of the cardinality of that element in the two + * given {@link Collection}s. * - * @param a the first collection, must not be null - * @param b the second collection, must not be null + * @param a the first collection, must not be null + * @param b the second collection, must not be null + * @param the generic type that is able to represent the types contained + * in both input collections. * @return the intersection of the two collections * @see Collection#retainAll * @see #containsAny */ - public static Collection intersection(final Collection a, final Collection b) { - ArrayList list = new ArrayList(); - Map mapa = getCardinalityMap(a); - Map mapb = getCardinalityMap(b); - Set elts = new HashSet(a); - elts.addAll(b); - Iterator it = elts.iterator(); - while(it.hasNext()) { - Object obj = it.next(); - for(int i=0,m=Math.min(getFreq(obj,mapa),getFreq(obj,mapb));i Collection intersection(final Iterable a, final Iterable b) { + SetOperationCardinalityHelper helper = new SetOperationCardinalityHelper(a, b); + for (O obj : helper) { + helper.setCardinality(obj, helper.min(obj)); } - return list; + return helper.list(); } /** * Returns a {@link Collection} containing the exclusive disjunction * (symmetric difference) of the given {@link Collection}s. *

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

* This is equivalent to * {@link #subtract subtract}({@link #union union(a,b)},{@link #intersection intersection(a,b)}) * or * {@link #union union}({@link #subtract subtract(a,b)},{@link #subtract subtract(b,a)}). - * - * @param a the first collection, must not be null - * @param b the second collection, must not be null + + * @param a the first collection, must not be null + * @param b the second collection, must not be null + * @param the generic type that is able to represent the types contained + * in both input collections. * @return the symmetric difference of the two collections */ - public static Collection disjunction(final Collection a, final Collection b) { - ArrayList list = new ArrayList(); - Map mapa = getCardinalityMap(a); - Map mapb = getCardinalityMap(b); - Set elts = new HashSet(a); - elts.addAll(b); - Iterator it = elts.iterator(); - while(it.hasNext()) { - Object obj = it.next(); - for(int i=0,m=((Math.max(getFreq(obj,mapa),getFreq(obj,mapb)))-(Math.min(getFreq(obj,mapa),getFreq(obj,mapb))));i Collection disjunction(final Iterable a, final Iterable b) { + SetOperationCardinalityHelper helper = new SetOperationCardinalityHelper(a, b); + for (O obj : helper) { + helper.setCardinality(obj, helper.max(obj) - helper.min(obj)); } - return list; + return helper.list(); } /** @@ -174,13 +230,16 @@ * * @param a the collection to subtract from, must not be null * @param b the collection to subtract, must not be null + * @param the generic type that is able to represent the types contained + * in both input collections. * @return a new collection with the results * @see Collection#removeAll */ - public static Collection subtract(final Collection a, final Collection b) { - ArrayList list = new ArrayList( a ); - for (Iterator it = b.iterator(); it.hasNext();) { - list.remove(it.next()); + public static Collection subtract(final Iterable a, final Iterable b) { + ArrayList list = new ArrayList(); + addAll(list, a); + for (O element : b) { + list.remove(element); } return list; } @@ -190,23 +249,23 @@ *

* In other words, this method returns true iff the * {@link #intersection} of coll1 and coll2 is not empty. - * + * * @param coll1 the first collection, must not be null * @param coll2 the first collection, must not be null * @return true iff the intersection of the collections is non-empty * @since 2.1 * @see #intersection */ - public static boolean containsAny(final Collection coll1, final Collection coll2) { + public static boolean containsAny(final Collection coll1, final Collection coll2) { if (coll1.size() < coll2.size()) { - for (Iterator it = coll1.iterator(); it.hasNext();) { - if (coll2.contains(it.next())) { + for (Object aColl1 : coll1) { + if (coll2.contains(aColl1)) { return true; } } } else { - for (Iterator it = coll2.iterator(); it.hasNext();) { - if (coll1.contains(it.next())) { + for (Object aColl2 : coll2) { + if (coll1.contains(aColl2)) { return true; } } @@ -221,19 +280,23 @@ *

* Only those elements present in the collection will appear as * keys in the map. - * - * @param coll the collection to get the cardinality map for, must not be null + * + * @param coll + * the collection to get the cardinality map for, must not be + * null + * @param + * the type of object in the returned {@link Map}. This is a + * super type of . * @return the populated cardinality map */ - public static Map getCardinalityMap(final Collection coll) { - Map count = new HashMap(); - for (Iterator it = coll.iterator(); it.hasNext();) { - Object obj = it.next(); - Integer c = (Integer) (count.get(obj)); + public static Map getCardinalityMap(final Iterable coll) { + Map count = new HashMap(); + for (O obj : coll) { + Integer c = count.get(obj); if (c == null) { - count.put(obj,INTEGER_ONE); + count.put(obj, 1); } else { - count.put(obj,new Integer(c.intValue() + 1)); + count.put(obj, c + 1); } } return count; @@ -241,23 +304,20 @@ /** * Returns true iff a is a sub-collection of b, - * that is, iff the cardinality of e in a is less - * than or equal to the cardinality of e in b, - * for each element e in a. + * that is, iff the cardinality of e in a is less than or + * equal to the cardinality of e in b, for each element e + * in a. * - * @param a the first (sub?) collection, must not be null - * @param b the second (super?) collection, must not be null + * @param a the first (sub?) collection, must not be null + * @param b the second (super?) collection, must not be null * @return true iff a is a sub-collection of b * @see #isProperSubCollection * @see Collection#containsAll */ - public static boolean isSubCollection(final Collection a, final Collection b) { - Map mapa = getCardinalityMap(a); - Map mapb = getCardinalityMap(b); - Iterator it = a.iterator(); - while (it.hasNext()) { - Object obj = it.next(); - if (getFreq(obj, mapa) > getFreq(obj, mapb)) { + public static boolean isSubCollection(final Collection a, final Collection b) { + CardinalityHelper helper = new CardinalityHelper(a, b); + for (Object obj : a) { + if (helper.freqA(obj) > helper.freqB(obj)) { return false; } } @@ -274,7 +334,7 @@ *

* The implementation assumes *

    - *
  • a.size() and b.size() represent the + *
  • a.size() and b.size() represent the * total cardinality of a and b, resp.
  • *
  • a.size() < Integer.MAXVALUE
  • *
@@ -285,8 +345,8 @@ * @see #isSubCollection * @see Collection#containsAll */ - public static boolean isProperSubCollection(final Collection a, final Collection b) { - return (a.size() < b.size()) && CollectionUtils.isSubCollection(a,b); + public static boolean isProperSubCollection(final Collection a, final Collection b) { + return (a.size() < b.size()) && CollectionUtils.isSubCollection(a, b); } /** @@ -301,51 +361,47 @@ * @param b the second collection, must not be null * @return true iff the collections contain the same elements with the same cardinalities. */ - public static boolean isEqualCollection(final Collection a, final Collection b) { + public static boolean isEqualCollection(final Collection a, final Collection b) { if(a.size() != b.size()) { return false; - } else { - Map mapa = getCardinalityMap(a); - Map mapb = getCardinalityMap(b); - if(mapa.size() != mapb.size()) { + } + final CardinalityHelper helper = new CardinalityHelper(a, b); + if(helper.cardinalityA.size() != helper.cardinalityB.size()) { + return false; + } + for( Object obj : helper.cardinalityA.keySet()) { + if(helper.freqA(obj) != helper.freqB(obj)) { return false; - } else { - Iterator it = mapa.keySet().iterator(); - while(it.hasNext()) { - Object obj = it.next(); - if(getFreq(obj,mapa) != getFreq(obj,mapb)) { - return false; - } - } - return true; } } + return true; } /** * Returns the number of occurrences of obj in coll. * - * @param obj the object to find the cardinality of - * @param coll the collection to search + * @param obj the object to find the cardinality of + * @param coll the {@link Iterable} to search + * @param the type of object that the {@link Iterable} may contain. * @return the the number of occurrences of obj in coll */ - public static int cardinality(Object obj, final Collection coll) { - if (coll instanceof Set) { - return (coll.contains(obj) ? 1 : 0); + public static int cardinality(O obj, final Iterable coll) { + if (coll instanceof Set) { + return (((Set) coll).contains(obj) ? 1 : 0); } - if (coll instanceof Bag) { - return ((Bag) coll).getCount(obj); + if (coll instanceof Bag) { + return ((Bag) coll).getCount(obj); } int count = 0; if (obj == null) { - for (Iterator it = coll.iterator();it.hasNext();) { - if (it.next() == null) { + for (Object element : coll) { + if (element == null) { count++; } } } else { - for (Iterator it = coll.iterator();it.hasNext();) { - if (obj.equals(it.next())) { + for (Object element : coll) { + if (obj.equals(element)) { count++; } } @@ -353,20 +409,19 @@ return count; } - /** + /** * Finds the first element in the given collection which matches the given predicate. *

- * If the input collection or predicate is null, or no element of the collection + * If the input collection or predicate is null, or no element of the collection * matches the predicate, null is returned. * * @param collection the collection to search, may be null * @param predicate the predicate to use, may be null * @return the first element of the collection which matches the predicate or null if none could be found */ - public static Object find(Collection collection, Predicate predicate) { + public static T find(Collection collection, Predicate predicate) { if (collection != null && predicate != null) { - for (Iterator iter = collection.iterator(); iter.hasNext();) { - Object item = iter.next(); + for (T item : collection) { if (predicate.evaluate(item)) { return item; } @@ -374,87 +429,99 @@ } return null; } - - /** + + /** * Executes the given closure on each element in the collection. *

* If the input collection or closure is null, there is no change made. - * - * @param collection the collection to get the input from, may be null - * @param closure the closure to perform, may be null + * + * @param collection + * the collection to get the input from, may be null + * @param closure + * the closure to perform, may be null + * @return closure */ - public static void forAllDo(Collection collection, Closure closure) { + public static > C forAllDo(Collection collection, C closure) { if (collection != null && closure != null) { - for (Iterator it = collection.iterator(); it.hasNext();) { - closure.execute(it.next()); + for (T element : collection) { + closure.execute(element); } } + return closure; } - /** + /** * Filter the collection by applying a Predicate to each element. If the * predicate returns false, remove the element. *

* If the input collection or predicate is null, there is no change made. - * - * @param collection the collection to get the input from, may be null - * @param predicate the predicate to use as a filter, may be null + * + * @param collection + * the collection to get the input from, may be null + * @param predicate + * the predicate to use as a filter, may be null */ - public static void filter(Collection collection, Predicate predicate) { + public static void filter(Iterable collection, Predicate predicate) { if (collection != null && predicate != null) { - for (Iterator it = collection.iterator(); it.hasNext();) { - if (predicate.evaluate(it.next()) == false) { + for (Iterator it = collection.iterator(); it.hasNext();) { + if (!predicate.evaluate(it.next())) { it.remove(); } } } } - /** + /** * Transform the collection by applying a Transformer to each element. *

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

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

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

* A null collection or predicate matches no elements. - * - * @param inputCollection the collection to get the input from, may be null - * @param predicate the predicate to use, may be null + * + * @param input + * the {@link Iterable} to get the input from, may be null + * @param predicate + * the predicate to use, may be null * @return the number of matches for the predicate in the collection */ - public static int countMatches(Collection inputCollection, Predicate predicate) { + public static int countMatches(Iterable input, Predicate predicate) { int count = 0; - if (inputCollection != null && predicate != null) { - for (Iterator it = inputCollection.iterator(); it.hasNext();) { - if (predicate.evaluate(it.next())) { + if (input != null && predicate != null) { + for (C o : input) { + if (predicate.evaluate(o)) { count++; } } @@ -462,19 +529,23 @@ return count; } - /** - * Answers true if a predicate is true for at least one element of a collection. + /** + * Answers true if a predicate is true for at least one element of a + * collection. *

* A null collection or predicate returns false. - * - * @param collection the collection to get the input from, may be null - * @param predicate the predicate to use, may be null - * @return true if at least one element of the collection matches the predicate - */ - public static boolean exists(Collection collection, Predicate predicate) { - if (collection != null && predicate != null) { - for (Iterator it = collection.iterator(); it.hasNext();) { - if (predicate.evaluate(it.next())) { + * + * @param input + * the {@link Iterable} to get the input from, may be null + * @param predicate + * the predicate to use, may be null + * @return true if at least one element of the collection matches the + * predicate + */ + public static boolean exists(Iterable input, Predicate predicate) { + if (input != null && predicate != null) { + for (C o : input) { + if (predicate.evaluate(o)) { return true; } } @@ -482,154 +553,191 @@ return false; } - /** - * Selects all elements from input collection which match the given predicate - * into an output collection. + /** + * Selects all elements from input collection which match the given + * predicate into an output collection. *

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

- * If the input collection or predicate is null, there is no change to the + * If the input collection or predicate is null, there is no change to the * output collection. - * - * @param inputCollection the collection to get the input from, may be null - * @param predicate the predicate to use, may be null - * @param outputCollection the collection to output into, may not be null + * + * @param inputCollection + * the collection to get the input from, may be null + * @param predicate + * the predicate to use, may be null + * @param outputCollection + * the collection to output into, may not be null + * @return outputCollection */ - public static void select(Collection inputCollection, Predicate predicate, Collection outputCollection) { + public static > R select(Collection inputCollection, + Predicate predicate, R outputCollection) { if (inputCollection != null && predicate != null) { - for (Iterator iter = inputCollection.iterator(); iter.hasNext();) { - Object item = iter.next(); + for (O item : inputCollection) { if (predicate.evaluate(item)) { outputCollection.add(item); } } } + return outputCollection; } - + /** - * Selects all elements from inputCollection which don't match the given predicate - * into an output collection. + * Selects all elements from inputCollection which don't match the given + * predicate into an output collection. *

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

- * If the input predicate is null, no elements are added to outputCollection. - * - * @param inputCollection the collection to get the input from, may be null - * @param predicate the predicate to use, may be null - * @param outputCollection the collection to output into, may not be null + * If the input predicate is null, no elements are added to + * outputCollection. + * + * @param inputCollection + * the collection to get the input from, may be null + * @param predicate + * the predicate to use, may be null + * @param outputCollection + * the collection to output into, may not be null + * @return outputCollection */ - public static void selectRejected(Collection inputCollection, Predicate predicate, Collection outputCollection) { + public static > R selectRejected( + Collection inputCollection, Predicate predicate, R outputCollection) { if (inputCollection != null && predicate != null) { - for (Iterator iter = inputCollection.iterator(); iter.hasNext();) { - Object item = iter.next(); - if (predicate.evaluate(item) == false) { + for (O item : inputCollection) { + if (!predicate.evaluate(item)) { outputCollection.add(item); } } } + return outputCollection; } - - /** - * Returns a new Collection consisting of the elements of inputCollection transformed - * by the given transformer. + + /** + * Returns a new Collection consisting of the elements of inputCollection + * transformed by the given transformer. *

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

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

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

- * If the input iterator or transformer is null, there is no change to the + * If the input iterator or transformer is null, there is no change to the * output collection. * * @param inputIterator the iterator to get the input from, may be null * @param transformer the transformer to use, may be null * @param outputCollection the collection to output into, may not be null + * @param the type of object in the input collection + * @param the type of object in the output collection + * @param the output type of the transformer - this extends O. * @return the outputCollection with the transformed input added * @throws NullPointerException if the output collection is null */ - public static Collection collect(Iterator inputIterator, final Transformer transformer, final Collection outputCollection) { + //TODO - deprecate and replace with IteratorIterable + public static > R collect(Iterator inputIterator, + final Transformer transformer, final R outputCollection) { if (inputIterator != null && transformer != null) { while (inputIterator.hasNext()) { - Object item = inputIterator.next(); - Object value = transformer.transform(item); + I item = inputIterator.next(); + O value = transformer.transform(item); outputCollection.add(value); } } @@ -639,187 +747,168 @@ //----------------------------------------------------------------------- /** * Adds an element to the collection unless the element is null. - * + * * @param collection the collection to add to, must not be null * @param object the object to add, if null it will not be added * @return true if the collection changed * @throws NullPointerException if the collection is null * @since Commons Collections 3.2 */ - public static boolean addIgnoreNull(Collection collection, Object object) { + public static boolean addIgnoreNull(Collection collection, T object) { return (object == null ? false : collection.add(object)); } - + + /** + * Adds all elements in the {@link Iterable} to the given collection. If the + * {@link Iterable} is a {@link Collection} then it is cast and will be + * added using {@link Collection#addAll(Collection)} instead of iterating. + * + * @param collection + * the collection to add to, must not be null + * @param iterable + * the iterable of elements to add, must not be null + * @return a boolean indicating whether the collection has changed or not. + * @throws NullPointerException + * if the collection or iterator is null + */ + public static boolean addAll(Collection collection, Iterable iterable) { + if (iterable instanceof Collection) { + return collection.addAll((Collection) iterable); + } + return addAll(collection, iterable.iterator()); + } + /** * Adds all elements in the iteration to the given collection. - * - * @param collection the collection to add to, must not be null - * @param iterator the iterator of elements to add, must not be null - * @throws NullPointerException if the collection or iterator is null + * + * @param collection + * the collection to add to, must not be null + * @param iterator + * the iterator of elements to add, must not be null + * @return a boolean indicating whether the collection has changed or not. + * @throws NullPointerException + * if the collection or iterator is null */ - public static void addAll(Collection collection, Iterator iterator) { + public static boolean addAll(Collection collection, Iterator iterator) { + boolean changed = false; while (iterator.hasNext()) { - collection.add(iterator.next()); + changed |= collection.add(iterator.next()); } + return changed; } - + /** * Adds all elements in the enumeration to the given collection. - * + * * @param collection the collection to add to, must not be null * @param enumeration the enumeration of elements to add, must not be null * @throws NullPointerException if the collection or enumeration is null */ - public static void addAll(Collection collection, Enumeration enumeration) { + //TODO return boolean or collection - check other add() methods too. + public static void addAll(Collection collection, Enumeration enumeration) { while (enumeration.hasMoreElements()) { collection.add(enumeration.nextElement()); } - } - - /** + } + + /** * Adds all elements in the array to the given collection. - * - * @param collection the collection to add to, must not be null - * @param elements the array of elements to add, must not be null - * @throws NullPointerException if the collection or array is null + * + * @param collection + * the collection to add to, must not be null + * @param elements + * the array of elements to add, must not be null + * @throws NullPointerException + * if the collection or array is null */ - public static void addAll(Collection collection, Object[] elements) { + public static void addAll(Collection collection, C[] elements) { for (int i = 0, size = elements.length; i < size; i++) { collection.add(elements[i]); } - } - - /** - * Given an Object, and an index, returns the nth value in the - * object. - *

    - *
  • If obj is a Map, returns the nth value from the keySet iterator, unless - * the Map contains an Integer key with integer value = idx, in which case the - * corresponding map entry value is returned. If idx exceeds the number of entries in - * the map, an empty Iterator is returned. - *
  • If obj is a List or an array, returns the nth value, throwing IndexOutOfBoundsException, - * ArrayIndexOutOfBoundsException, resp. if the nth value does not exist. - *
  • If obj is an iterator, enumeration or Collection, returns the nth value from the iterator, - * returning an empty Iterator (resp. Enumeration) if the nth value does not exist. - *
  • Returns the original obj if it is null or not a Collection or Iterator. - *
- * - * @param obj the object to get an index of, may be null - * @param idx the index to get - * @throws IndexOutOfBoundsException - * @throws ArrayIndexOutOfBoundsException - * - * @deprecated use {@link #get(Object, int)} instead. Will be removed in v4.0 - */ - public static Object index(Object obj, int idx) { - return index(obj, new Integer(idx)); } - + /** - * Given an Object, and a key (index), returns the value associated with - * that key in the Object. The following checks are made: - *
    - *
  • If obj is a Map, use the index as a key to get a value. If no match continue. - *
  • Check key is an Integer. If not, return the object passed in. - *
  • If obj is a Map, get the nth value from the keySet iterator. - * If the Map has fewer than n entries, return an empty Iterator. - *
  • If obj is a List or an array, get the nth value, throwing IndexOutOfBoundsException, - * ArrayIndexOutOfBoundsException, resp. if the nth value does not exist. - *
  • If obj is an iterator, enumeration or Collection, get the nth value from the iterator, - * returning an empty Iterator (resp. Enumeration) if the nth value does not exist. - *
  • Return the original obj. - *
- * - * @param obj the object to get an index of + * Returns the index-th value in {@link Iterator}, throwing + * IndexOutOfBoundsException if there is no such element. + * The Iterator is advanced to + * index (or to the end, if index exceeds the + * number of entries) as a side effect of this method. + * + * @param iterator the iterator to get a value from * @param index the index to get + * @param the type of object in the {@link Iterator} * @return the object at the specified index - * @throws IndexOutOfBoundsException - * @throws ArrayIndexOutOfBoundsException - * - * @deprecated use {@link #get(Object, int)} instead. Will be removed in v4.0 + * @throws IndexOutOfBoundsException if the index is invalid + * @throws IllegalArgumentException if the object type is invalid */ - public static Object index(Object obj, Object index) { - if(obj instanceof Map) { - Map map = (Map)obj; - if(map.containsKey(index)) { - return map.get(index); - } - } - int idx = -1; - if(index instanceof Integer) { - idx = ((Integer)index).intValue(); - } - if(idx < 0) { - return obj; - } - else if(obj instanceof Map) { - Map map = (Map)obj; - Iterator iterator = map.keySet().iterator(); - return index(iterator, idx); - } - else if(obj instanceof List) { - return ((List)obj).get(idx); - } - else if(obj instanceof Object[]) { - return ((Object[])obj)[idx]; - } - else if(obj instanceof Enumeration) { - Enumeration it = (Enumeration)obj; - while(it.hasMoreElements()) { - idx--; - if(idx == -1) { - return it.nextElement(); - } else { - it.nextElement(); + public static T get(Iterator iterator, int index) { + int i = index; + checkIndexBounds(i); + while (iterator.hasNext()) { + i--; + if (i == -1) { + return iterator.next(); } - } - } - else if(obj instanceof Iterator) { - return index((Iterator)obj, idx); - } - else if(obj instanceof Collection) { - Iterator iterator = ((Collection)obj).iterator(); - return index(iterator, idx); - } - return obj; - } - - private static Object index(Iterator iterator, int idx) { - while(iterator.hasNext()) { - idx--; - if(idx == -1) { - return iterator.next(); - } else { iterator.next(); } + throw new IndexOutOfBoundsException("Entry does not exist: " + i); + } + + /** + * Ensures an index is not negative. + * @param index the index to check. + * @throws IndexOutOfBoundsException if the index is negative. + */ + private static void checkIndexBounds(int index) { + if (index < 0) { + throw new IndexOutOfBoundsException("Index cannot be negative: " + index); } - return iterator; } - + + /** + * Returns the index-th value in the iterable's {@link Iterator}, throwing + * IndexOutOfBoundsException if there is no such element. + *

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

* The supported types, and associated semantics are: *

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

* This method can handles objects as follows @@ -885,7 +986,7 @@ *

  • Iterator - the number of elements remaining in the iterator *
  • Enumeration - the number of elements remaining in the enumeration * - * + * * @param object the object to get the size of, may be null * @return the size of the specified collection or 0 if the object was null * @throws IllegalArgumentException thrown if object is not recognised @@ -896,20 +997,20 @@ return 0; } int total = 0; - if (object instanceof Map) { - total = ((Map) object).size(); - } else if (object instanceof Collection) { - total = ((Collection) object).size(); + if (object instanceof Map) { + total = ((Map) object).size(); + } else if (object instanceof Collection) { + total = ((Collection) object).size(); } else if (object instanceof Object[]) { total = ((Object[]) object).length; - } else if (object instanceof Iterator) { - Iterator it = (Iterator) object; + } else if (object instanceof Iterator) { + Iterator it = (Iterator) object; while (it.hasNext()) { total++; it.next(); } - } else if (object instanceof Enumeration) { - Enumeration it = (Enumeration) object; + } else if (object instanceof Enumeration) { + Enumeration it = (Enumeration) object; while (it.hasMoreElements()) { total++; it.nextElement(); @@ -923,7 +1024,7 @@ } return total; } - + /** * Checks if the specified collection/array/iterator is empty. *

    @@ -938,7 +1039,7 @@ *

    * Note: This method is named to avoid clashing with * {@link #isEmpty(Collection)}. - * + * * @param object the object to get the size of, may be null * @return true if empty or null * @throws IllegalArgumentException thrown if object is not recognised @@ -947,16 +1048,16 @@ public static boolean sizeIsEmpty(Object object) { if (object == null) { return true; - } else if (object instanceof Collection) { - return ((Collection) object).isEmpty(); - } else if (object instanceof Map) { - return ((Map) object).isEmpty(); + } else if (object instanceof Collection) { + return ((Collection) object).isEmpty(); + } else if (object instanceof Map) { + return ((Map) object).isEmpty(); } else if (object instanceof Object[]) { return ((Object[]) object).length == 0; - } else if (object instanceof Iterator) { - return ((Iterator) object).hasNext() == false; - } else if (object instanceof Enumeration) { - return ((Enumeration) object).hasMoreElements() == false; + } else if (object instanceof Iterator) { + return ((Iterator) object).hasNext() == false; + } else if (object instanceof Enumeration) { + return ((Enumeration) object).hasMoreElements() == false; } else { try { return Array.getLength(object) == 0; @@ -971,12 +1072,12 @@ * Null-safe check if the specified collection is empty. *

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

    * Null returns false. - * + * * @param coll the collection to check, may be null * @return true if non-null and non-empty * @since Commons Collections 3.2 */ - public static boolean isNotEmpty(Collection coll) { - return !CollectionUtils.isEmpty(coll); + public static boolean isNotEmpty(Collection coll) { + return !isEmpty(coll); } //----------------------------------------------------------------------- /** * Reverses the order of the given array. - * + * * @param array the array to reverse */ public static void reverseArray(Object[] array) { @@ -1013,14 +1114,6 @@ } } - private static final int getFreq(final Object obj, final Map freqMap) { - Integer count = (Integer) freqMap.get(obj); - if (count != null) { - return count.intValue(); - } - return 0; - } - /** * Returns true if no more elements can be added to the Collection. *

    @@ -1036,17 +1129,17 @@ * @return true if the BoundedCollection is full * @throws NullPointerException if the collection is null */ - public static boolean isFull(Collection coll) { + @SuppressWarnings("unchecked") + public static boolean isFull(Collection coll) { if (coll == null) { throw new NullPointerException("The collection must not be null"); } if (coll instanceof BoundedCollection) { - return ((BoundedCollection) coll).isFull(); + return ((BoundedCollection) coll).isFull(); } try { - BoundedCollection bcoll = UnmodifiableBoundedCollection.decorateUsing(coll); + BoundedCollection bcoll = UnmodifiableBoundedCollection.decorateUsing((Collection) coll); return bcoll.isFull(); - } catch (IllegalArgumentException ex) { return false; } @@ -1067,17 +1160,17 @@ * @return the maximum size of the BoundedCollection, -1 if no maximum size * @throws NullPointerException if the collection is null */ - public static int maxSize(Collection coll) { + @SuppressWarnings("unchecked") + public static int maxSize(Collection coll) { if (coll == null) { throw new NullPointerException("The collection must not be null"); } if (coll instanceof BoundedCollection) { - return ((BoundedCollection) coll).maxSize(); + return ((BoundedCollection) coll).maxSize(); } try { - BoundedCollection bcoll = UnmodifiableBoundedCollection.decorateUsing(coll); + BoundedCollection bcoll = UnmodifiableBoundedCollection.decorateUsing((Collection) coll); return bcoll.maxSize(); - } catch (IllegalArgumentException ex) { return -1; } @@ -1091,7 +1184,7 @@ * in collection unless retain does not contain e, in which * case the cardinality is zero. This method is useful if you do not wish to modify * the collection c and thus cannot call c.retainAll(retain);. - * + * * @param collection the collection whose contents are the target of the #retailAll operation * @param retain the collection containing the elements to be retained in the returned collection * @return a Collection containing all the elements of collection @@ -1099,7 +1192,7 @@ * @throws NullPointerException if either parameter is null * @since Commons Collections 3.2 */ - public static Collection retainAll(Collection collection, Collection retain) { + public static Collection retainAll(Collection collection, Collection retain) { return ListUtils.retainAll(collection, retain); } @@ -1111,7 +1204,7 @@ * in collection unless remove contains e, in which * case the cardinality is zero. This method is useful if you do not wish to modify * the collection c and thus cannot call collection.removeAll(remove);. - * + * * @param collection the collection from which items are removed (in the returned collection) * @param remove the items to be removed from the returned collection * @return a Collection containing all the elements of collection except @@ -1119,7 +1212,7 @@ * @throws NullPointerException if either parameter is null * @since Commons Collections 3.3 (method existed in 3.2 but was completely broken) */ - public static Collection removeAll(Collection collection, Collection remove) { + public static Collection removeAll(Collection collection, Collection remove) { return ListUtils.removeAll(collection, remove); } @@ -1127,9 +1220,9 @@ /** * Returns a synchronized collection backed by the given collection. *

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

          * Collection c = CollectionUtils.synchronizedCollection(myCollection);
          * synchronized (c) {
    @@ -1139,14 +1232,14 @@
          *     }
          * }
          * 
    - * + * * This method uses the implementation in the decorators subpackage. - * + * * @param collection the collection to synchronize, must not be null * @return a synchronized collection backed by the given collection * @throws IllegalArgumentException if the collection is null */ - public static Collection synchronizedCollection(Collection collection) { + public static Collection synchronizedCollection(Collection collection) { return SynchronizedCollection.decorate(collection); } @@ -1159,7 +1252,7 @@ * @return an unmodifiable collection backed by the given collection * @throws IllegalArgumentException if the collection is null */ - public static Collection unmodifiableCollection(Collection collection) { + public static Collection unmodifiableCollection(Collection collection) { return UnmodifiableCollection.decorate(collection); } @@ -1173,31 +1266,19 @@ * * @param collection the collection to predicate, must not be null * @param predicate the predicate for the collection, must not be null + * @param the type of objects in the Collection. * @return a predicated collection backed by the given collection * @throws IllegalArgumentException if the Collection is null */ - public static Collection predicatedCollection(Collection collection, Predicate predicate) { + public static Collection predicatedCollection(Collection collection, Predicate predicate) { return PredicatedCollection.decorate(collection, predicate); } /** - * Returns a typed collection backed by the given collection. - *

    - * Only objects of the specified type can be added to the collection. - * - * @param collection the collection to limit to a specific type, must not be null - * @param type the type of objects which may be added to the collection - * @return a typed collection backed by the specified collection - */ - public static Collection typedCollection(Collection collection, Class type) { - return TypedCollection.decorate(collection, type); - } - - /** * Returns a transformed bag backed by the given collection. *

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

    * Existing entries in the specified collection will not be transformed. @@ -1208,8 +1289,21 @@ * @return a transformed collection backed by the given collection * @throws IllegalArgumentException if the Collection or Transformer is null */ - public static Collection transformedCollection(Collection collection, Transformer transformer) { + public static Collection transformedCollection(Collection collection, Transformer transformer) { return TransformedCollection.decorate(collection, transformer); } + /** + * Extract the lone element of the specified Collection. + * @param collection type + * @param collection to read + * @return sole member of collection + * @throws IllegalArgumentException if collection is null/empty or contains more than one element + */ + public static E extractSingleton(Collection collection) { + if (collection == null || collection.size() != 1) { + throw new IllegalArgumentException("Can extract singleton only when collection size == 1"); + } + return collection.iterator().next(); + } }