KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > collections > CollectionUtils


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.collections;
17
18 import java.lang.reflect.Array JavaDoc;
19 import java.util.ArrayList JavaDoc;
20 import java.util.Collection JavaDoc;
21 import java.util.Enumeration JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.HashSet JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.ListIterator JavaDoc;
27 import java.util.Map JavaDoc;
28 import java.util.Set JavaDoc;
29
30 import org.apache.commons.collections.collection.PredicatedCollection;
31 import org.apache.commons.collections.collection.SynchronizedCollection;
32 import org.apache.commons.collections.collection.TransformedCollection;
33 import org.apache.commons.collections.collection.TypedCollection;
34 import org.apache.commons.collections.collection.UnmodifiableBoundedCollection;
35 import org.apache.commons.collections.collection.UnmodifiableCollection;
36
37 /**
38  * Provides utility methods and decorators for {@link Collection} instances.
39  *
40  * @since Commons Collections 1.0
41  * @version $Revision: 1.61 $ $Date: 2004/04/27 20:00:18 $
42  *
43  * @author Rodney Waldhoff
44  * @author Paul Jack
45  * @author Stephen Colebourne
46  * @author Steve Downey
47  * @author Herve Quiroz
48  * @author Peter KoBek
49  * @author Matthew Hawthorne
50  * @author Janek Bogucki
51  * @author Phil Steitz
52  * @author Steven Melzer
53  * @author Jon Schewe
54  */

55 public class CollectionUtils {
56
57     /** Constant to avoid repeated object creation */
58     private static Integer JavaDoc INTEGER_ONE = new Integer JavaDoc(1);
59
60     /**
61      * An empty unmodifiable collection.
62      * The JDK provides empty Set and List implementations which could be used for
63      * this purpose. However they could be cast to Set or List which might be
64      * undesirable. This implementation only implements Collection.
65      */

66     public static final Collection JavaDoc EMPTY_COLLECTION = UnmodifiableCollection.decorate(new ArrayList JavaDoc());
67
68     /**
69      * <code>CollectionUtils</code> should not normally be instantiated.
70      */

71     public CollectionUtils() {
72     }
73
74     /**
75      * Returns a {@link Collection} containing the union
76      * of the given {@link Collection}s.
77      * <p>
78      * The cardinality of each element in the returned {@link Collection}
79      * will be equal to the maximum of the cardinality of that element
80      * in the two given {@link Collection}s.
81      *
82      * @param a the first collection, must not be null
83      * @param b the second collection, must not be null
84      * @return the union of the two collections
85      * @see Collection#addAll
86      */

87     public static Collection JavaDoc union(final Collection JavaDoc a, final Collection JavaDoc b) {
88         ArrayList JavaDoc list = new ArrayList JavaDoc();
89         Map JavaDoc mapa = getCardinalityMap(a);
90         Map JavaDoc mapb = getCardinalityMap(b);
91         Set JavaDoc elts = new HashSet JavaDoc(a);
92         elts.addAll(b);
93         Iterator JavaDoc it = elts.iterator();
94         while(it.hasNext()) {
95             Object JavaDoc obj = it.next();
96             for(int i=0,m=Math.max(getFreq(obj,mapa),getFreq(obj,mapb));i<m;i++) {
97                 list.add(obj);
98             }
99         }
100         return list;
101     }
102
103     /**
104      * Returns a {@link Collection} containing the intersection
105      * of the given {@link Collection}s.
106      * <p>
107      * The cardinality of each element in the returned {@link Collection}
108      * will be equal to the minimum of the cardinality of that element
109      * in the two given {@link Collection}s.
110      *
111      * @param a the first collection, must not be null
112      * @param b the second collection, must not be null
113      * @return the intersection of the two collections
114      * @see Collection#retainAll
115      * @see #containsAny
116      */

117     public static Collection JavaDoc intersection(final Collection JavaDoc a, final Collection JavaDoc b) {
118         ArrayList JavaDoc list = new ArrayList JavaDoc();
119         Map JavaDoc mapa = getCardinalityMap(a);
120         Map JavaDoc mapb = getCardinalityMap(b);
121         Set JavaDoc elts = new HashSet JavaDoc(a);
122         elts.addAll(b);
123         Iterator JavaDoc it = elts.iterator();
124         while(it.hasNext()) {
125             Object JavaDoc obj = it.next();
126             for(int i=0,m=Math.min(getFreq(obj,mapa),getFreq(obj,mapb));i<m;i++) {
127                 list.add(obj);
128             }
129         }
130         return list;
131     }
132
133     /**
134      * Returns a {@link Collection} containing the exclusive disjunction
135      * (symmetric difference) of the given {@link Collection}s.
136      * <p>
137      * The cardinality of each element <i>e</i> in the returned {@link Collection}
138      * will be equal to
139      * <tt>max(cardinality(<i>e</i>,<i>a</i>),cardinality(<i>e</i>,<i>b</i>)) - min(cardinality(<i>e</i>,<i>a</i>),cardinality(<i>e</i>,<i>b</i>))</tt>.
140      * <p>
141      * This is equivalent to
142      * <tt>{@link #subtract subtract}({@link #union union(a,b)},{@link #intersection intersection(a,b)})</tt>
143      * or
144      * <tt>{@link #union union}({@link #subtract subtract(a,b)},{@link #subtract subtract(b,a)})</tt>.
145      *
146      * @param a the first collection, must not be null
147      * @param b the second collection, must not be null
148      * @return the symmetric difference of the two collections
149      */

150     public static Collection JavaDoc disjunction(final Collection JavaDoc a, final Collection JavaDoc b) {
151         ArrayList JavaDoc list = new ArrayList JavaDoc();
152         Map JavaDoc mapa = getCardinalityMap(a);
153         Map JavaDoc mapb = getCardinalityMap(b);
154         Set JavaDoc elts = new HashSet JavaDoc(a);
155         elts.addAll(b);
156         Iterator JavaDoc it = elts.iterator();
157         while(it.hasNext()) {
158             Object JavaDoc obj = it.next();
159             for(int i=0,m=((Math.max(getFreq(obj,mapa),getFreq(obj,mapb)))-(Math.min(getFreq(obj,mapa),getFreq(obj,mapb))));i<m;i++) {
160                 list.add(obj);
161             }
162         }
163         return list;
164     }
165
166     /**
167      * Returns a new {@link Collection} containing <tt><i>a</i> - <i>b</i></tt>.
168      * The cardinality of each element <i>e</i> in the returned {@link Collection}
169      * will be the cardinality of <i>e</i> in <i>a</i> minus the cardinality
170      * of <i>e</i> in <i>b</i>, or zero, whichever is greater.
171      *
172      * @param a the collection to subtract from, must not be null
173      * @param b the collection to subtract, must not be null
174      * @return a new collection with the results
175      * @see Collection#removeAll
176      */

177     public static Collection JavaDoc subtract(final Collection JavaDoc a, final Collection JavaDoc b) {
178         ArrayList JavaDoc list = new ArrayList JavaDoc( a );
179         for (Iterator JavaDoc it = b.iterator(); it.hasNext();) {
180             list.remove(it.next());
181         }
182         return list;
183     }
184
185     /**
186      * Returns <code>true</code> iff at least one element is in both collections.
187      * <p>
188      * In other words, this method returns <code>true</code> iff the
189      * {@link #intersection} of <i>coll1</i> and <i>coll2</i> is not empty.
190      *
191      * @param coll1 the first collection, must not be null
192      * @param coll2 the first collection, must not be null
193      * @return <code>true</code> iff the intersection of the collections is non-empty
194      * @since 2.1
195      * @see #intersection
196      */

197     public static boolean containsAny(final Collection JavaDoc coll1, final Collection JavaDoc coll2) {
198         if (coll1.size() < coll2.size()) {
199             for (Iterator JavaDoc it = coll1.iterator(); it.hasNext();) {
200                 if (coll2.contains(it.next())) {
201                     return true;
202                 }
203             }
204         } else {
205             for (Iterator JavaDoc it = coll2.iterator(); it.hasNext();) {
206                 if (coll1.contains(it.next())) {
207                     return true;
208                 }
209             }
210         }
211         return false;
212     }
213
214     /**
215      * Returns a {@link Map} mapping each unique element in the given
216      * {@link Collection} to an {@link Integer} representing the number
217      * of occurrences of that element in the {@link Collection}.
218      * <p>
219      * Only those elements present in the collection will appear as
220      * keys in the map.
221      *
222      * @param coll the collection to get the cardinality map for, must not be null
223      * @return the populated cardinality map
224      */

225     public static Map JavaDoc getCardinalityMap(final Collection JavaDoc coll) {
226         Map JavaDoc count = new HashMap JavaDoc();
227         for (Iterator JavaDoc it = coll.iterator(); it.hasNext();) {
228             Object JavaDoc obj = it.next();
229             Integer JavaDoc c = (Integer JavaDoc) (count.get(obj));
230             if (c == null) {
231                 count.put(obj,INTEGER_ONE);
232             } else {
233                 count.put(obj,new Integer JavaDoc(c.intValue() + 1));
234             }
235         }
236         return count;
237     }
238
239     /**
240      * Returns <tt>true</tt> iff <i>a</i> is a sub-collection of <i>b</i>,
241      * that is, iff the cardinality of <i>e</i> in <i>a</i> is less
242      * than or equal to the cardinality of <i>e</i> in <i>b</i>,
243      * for each element <i>e</i> in <i>a</i>.
244      *
245      * @param a the first (sub?) collection, must not be null
246      * @param b the second (super?) collection, must not be null
247      * @return <code>true</code> iff <i>a</i> is a sub-collection of <i>b</i>
248      * @see #isProperSubCollection
249      * @see Collection#containsAll
250      */

251     public static boolean isSubCollection(final Collection JavaDoc a, final Collection JavaDoc b) {
252         Map JavaDoc mapa = getCardinalityMap(a);
253         Map JavaDoc mapb = getCardinalityMap(b);
254         Iterator JavaDoc it = a.iterator();
255         while (it.hasNext()) {
256             Object JavaDoc obj = it.next();
257             if (getFreq(obj, mapa) > getFreq(obj, mapb)) {
258                 return false;
259             }
260         }
261         return true;
262     }
263
264     /**
265      * Returns <tt>true</tt> iff <i>a</i> is a <i>proper</i> sub-collection of <i>b</i>,
266      * that is, iff the cardinality of <i>e</i> in <i>a</i> is less
267      * than or equal to the cardinality of <i>e</i> in <i>b</i>,
268      * for each element <i>e</i> in <i>a</i>, and there is at least one
269      * element <i>f</i> such that the cardinality of <i>f</i> in <i>b</i>
270      * is strictly greater than the cardinality of <i>f</i> in <i>a</i>.
271      * <p>
272      * The implementation assumes
273      * <ul>
274      * <li><code>a.size()</code> and <code>b.size()</code> represent the
275      * total cardinality of <i>a</i> and <i>b</i>, resp. </li>
276      * <li><code>a.size() < Integer.MAXVALUE</code></li>
277      * </ul>
278      *
279      * @param a the first (sub?) collection, must not be null
280      * @param b the second (super?) collection, must not be null
281      * @return <code>true</code> iff <i>a</i> is a <i>proper</i> sub-collection of <i>b</i>
282      * @see #isSubCollection
283      * @see Collection#containsAll
284      */

285     public static boolean isProperSubCollection(final Collection JavaDoc a, final Collection JavaDoc b) {
286         return (a.size() < b.size()) && CollectionUtils.isSubCollection(a,b);
287     }
288
289     /**
290      * Returns <tt>true</tt> iff the given {@link Collection}s contain
291      * exactly the same elements with exactly the same cardinalities.
292      * <p>
293      * That is, iff the cardinality of <i>e</i> in <i>a</i> is
294      * equal to the cardinality of <i>e</i> in <i>b</i>,
295      * for each element <i>e</i> in <i>a</i> or <i>b</i>.
296      *
297      * @param a the first collection, must not be null
298      * @param b the second collection, must not be null
299      * @return <code>true</code> iff the collections contain the same elements with the same cardinalities.
300      */

301     public static boolean isEqualCollection(final Collection JavaDoc a, final Collection JavaDoc b) {
302         if(a.size() != b.size()) {
303             return false;
304         } else {
305             Map JavaDoc mapa = getCardinalityMap(a);
306             Map JavaDoc mapb = getCardinalityMap(b);
307             if(mapa.size() != mapb.size()) {
308                 return false;
309             } else {
310                 Iterator JavaDoc it = mapa.keySet().iterator();
311                 while(it.hasNext()) {
312                     Object JavaDoc obj = it.next();
313                     if(getFreq(obj,mapa) != getFreq(obj,mapb)) {
314                         return false;
315                     }
316                 }
317                 return true;
318             }
319         }
320     }
321
322     /**
323      * Returns the number of occurrences of <i>obj</i> in <i>coll</i>.
324      *
325      * @param obj the object to find the cardinality of
326      * @param coll the collection to search
327      * @return the the number of occurrences of obj in coll
328      */

329     public static int cardinality(Object JavaDoc obj, final Collection JavaDoc coll) {
330         if (coll instanceof Set JavaDoc) {
331             return (coll.contains(obj) ? 1 : 0);
332         }
333         if (coll instanceof Bag) {
334             return ((Bag) coll).getCount(obj);
335         }
336         int count = 0;
337         if (obj == null) {
338             for (Iterator JavaDoc it = coll.iterator();it.hasNext();) {
339                 if (it.next() == null) {
340                     count++;
341                 }
342             }
343         } else {
344             for (Iterator JavaDoc it = coll.iterator();it.hasNext();) {
345                 if (obj.equals(it.next())) {
346                     count++;
347                 }
348             }
349         }
350         return count;
351     }
352
353     /**
354      * Finds the first element in the given collection which matches the given predicate.
355      * <p>
356      * If the input collection or predicate is null, or no element of the collection
357      * matches the predicate, null is returned.
358      *
359      * @param collection the collection to search, may be null
360      * @param predicate the predicate to use, may be null
361      * @return the first element of the collection which matches the predicate or null if none could be found
362      */

363     public static Object JavaDoc find(Collection JavaDoc collection, Predicate predicate) {
364         if (collection != null && predicate != null) {
365             for (Iterator JavaDoc iter = collection.iterator(); iter.hasNext();) {
366                 Object JavaDoc item = iter.next();
367                 if (predicate.evaluate(item)) {
368                     return item;
369                 }
370             }
371         }
372         return null;
373     }
374     
375     /**
376      * Executes the given closure on each element in the collection.
377      * <p>
378      * If the input collection or closure is null, there is no change made.
379      *
380      * @param collection the collection to get the input from, may be null
381      * @param closure the closure to perform, may be null
382      */

383     public static void forAllDo(Collection JavaDoc collection, Closure closure) {
384         if (collection != null && closure != null) {
385             for (Iterator JavaDoc it = collection.iterator(); it.hasNext();) {
386                 closure.execute(it.next());
387             }
388         }
389     }
390
391     /**
392      * Filter the collection by applying a Predicate to each element. If the
393      * predicate returns false, remove the element.
394      * <p>
395      * If the input collection or predicate is null, there is no change made.
396      *
397      * @param collection the collection to get the input from, may be null
398      * @param predicate the predicate to use as a filter, may be null
399      */

400     public static void filter(Collection JavaDoc collection, Predicate predicate) {
401         if (collection != null && predicate != null) {
402             for (Iterator JavaDoc it = collection.iterator(); it.hasNext();) {
403                 if (predicate.evaluate(it.next()) == false) {
404                     it.remove();
405                 }
406             }
407         }
408     }
409
410     /**
411      * Transform the collection by applying a Transformer to each element.
412      * <p>
413      * If the input collection or transformer is null, there is no change made.
414      * <p>
415      * This routine is best for Lists, for which set() is used to do the
416      * transformations "in place." For other Collections, clear() and addAll()
417      * are used to replace elements.
418      * <p>
419      * If the input collection controls its input, such as a Set, and the
420      * Transformer creates duplicates (or are otherwise invalid), the
421      * collection may reduce in size due to calling this method.
422      *
423      * @param collection the collection to get the input from, may be null
424      * @param transformer the transformer to perform, may be null
425      */

426     public static void transform(Collection JavaDoc collection, Transformer transformer) {
427         if (collection != null && transformer != null) {
428             if (collection instanceof List JavaDoc) {
429                 List JavaDoc list = (List JavaDoc) collection;
430                 for (ListIterator JavaDoc it = list.listIterator(); it.hasNext();) {
431                     it.set(transformer.transform(it.next()));
432                 }
433             } else {
434                 Collection JavaDoc resultCollection = collect(collection, transformer);
435                 collection.clear();
436                 collection.addAll(resultCollection);
437             }
438         }
439     }
440
441     /**
442      * Counts the number of elements in the input collection that match the predicate.
443      * <p>
444      * A <code>null</code> collection or predicate matches no elements.
445      *
446      * @param inputCollection the collection to get the input from, may be null
447      * @param predicate the predicate to use, may be null
448      * @return the number of matches for the predicate in the collection
449      */

450     public static int countMatches(Collection JavaDoc inputCollection, Predicate predicate) {
451         int count = 0;
452         if (inputCollection != null && predicate != null) {
453             for (Iterator JavaDoc it = inputCollection.iterator(); it.hasNext();) {
454                 if (predicate.evaluate(it.next())) {
455                     count++;
456                 }
457             }
458         }
459         return count;
460     }
461
462     /**
463      * Answers true if a predicate is true for at least one element of a collection.
464      * <p>
465      * A <code>null</code> collection or predicate returns false.
466      *
467      * @param collection the collection to get the input from, may be null
468      * @param predicate the predicate to use, may be null
469      * @return true if at least one element of the collection matches the predicate
470      */

471     public static boolean exists(Collection JavaDoc collection, Predicate predicate) {
472         if (collection != null && predicate != null) {
473             for (Iterator JavaDoc it = collection.iterator(); it.hasNext();) {
474                 if (predicate.evaluate(it.next())) {
475                     return true;
476                 }
477             }
478         }
479         return false;
480     }
481
482     /**
483      * Selects all elements from input collection which match the given predicate
484      * into an output collection.
485      * <p>
486      * A <code>null</code> predicate matches no elements.
487      *
488      * @param inputCollection the collection to get the input from, may not be null
489      * @param predicate the predicate to use, may be null
490      * @return the elements matching the predicate (new list)
491      * @throws NullPointerException if the input collection is null
492      */

493     public static Collection JavaDoc select(Collection JavaDoc inputCollection, Predicate predicate) {
494         ArrayList JavaDoc answer = new ArrayList JavaDoc(inputCollection.size());
495         select(inputCollection, predicate, answer);
496         return answer;
497     }
498
499     /**
500      * Selects all elements from input collection which match the given predicate
501      * and adds them to outputCollection.
502      * <p>
503      * If the input collection or predicate is null, there is no change to the
504      * output collection.
505      *
506      * @param inputCollection the collection to get the input from, may be null
507      * @param predicate the predicate to use, may be null
508      * @param outputCollection the collection to output into, may not be null
509      */

510     public static void select(Collection JavaDoc inputCollection, Predicate predicate, Collection JavaDoc outputCollection) {
511         if (inputCollection != null && predicate != null) {
512             for (Iterator JavaDoc iter = inputCollection.iterator(); iter.hasNext();) {
513                 Object JavaDoc item = iter.next();
514                 if (predicate.evaluate(item)) {
515                     outputCollection.add(item);
516                 }
517             }
518         }
519     }
520     
521     /**
522      * Selects all elements from inputCollection which don't match the given predicate
523      * into an output collection.
524      * <p>
525      * If the input predicate is <code>null</code>, the result is an empty list.
526      *
527      * @param inputCollection the collection to get the input from, may not be null
528      * @param predicate the predicate to use, may be null
529      * @return the elements <b>not</b> matching the predicate (new list)
530      * @throws NullPointerException if the input collection is null
531      */

532     public static Collection JavaDoc selectRejected(Collection JavaDoc inputCollection, Predicate predicate) {
533         ArrayList JavaDoc answer = new ArrayList JavaDoc(inputCollection.size());
534         selectRejected(inputCollection, predicate, answer);
535         return answer;
536     }
537     
538     /**
539      * Selects all elements from inputCollection which don't match the given predicate
540      * and adds them to outputCollection.
541      * <p>
542      * If the input predicate is <code>null</code>, no elements are added to <code>outputCollection</code>.
543      *
544      * @param inputCollection the collection to get the input from, may be null
545      * @param predicate the predicate to use, may be null
546      * @param outputCollection the collection to output into, may not be null
547      */

548     public static void selectRejected(Collection JavaDoc inputCollection, Predicate predicate, Collection JavaDoc outputCollection) {
549         if (inputCollection != null && predicate != null) {
550             for (Iterator JavaDoc iter = inputCollection.iterator(); iter.hasNext();) {
551                 Object JavaDoc item = iter.next();
552                 if (predicate.evaluate(item) == false) {
553                     outputCollection.add(item);
554                 }
555             }
556         }
557     }
558     
559     /**
560      * Returns a new Collection consisting of the elements of inputCollection transformed
561      * by the given transformer.
562      * <p>
563      * If the input transformer is null, the result is an empty list.
564      *
565      * @param inputCollection the collection to get the input from, may not be null
566      * @param transformer the transformer to use, may be null
567      * @return the transformed result (new list)
568      * @throws NullPointerException if the input collection is null
569      */

570     public static Collection JavaDoc collect(Collection JavaDoc inputCollection, Transformer transformer) {
571         ArrayList JavaDoc answer = new ArrayList JavaDoc(inputCollection.size());
572         collect(inputCollection, transformer, answer);
573         return answer;
574     }
575     
576     /**
577      * Transforms all elements from the inputIterator with the given transformer
578      * and adds them to the outputCollection.
579      * <p>
580      * If the input iterator or transformer is null, the result is an empty list.
581      *
582      * @param inputIterator the iterator to get the input from, may be null
583      * @param transformer the transformer to use, may be null
584      * @return the transformed result (new list)
585      */

586     public static Collection JavaDoc collect(Iterator JavaDoc inputIterator, Transformer transformer) {
587         ArrayList JavaDoc answer = new ArrayList JavaDoc();
588         collect(inputIterator, transformer, answer);
589         return answer;
590     }
591     
592     /**
593      * Transforms all elements from inputCollection with the given transformer
594      * and adds them to the outputCollection.
595      * <p>
596      * If the input collection or transformer is null, there is no change to the
597      * output collection.
598      *
599      * @param inputCollection the collection to get the input from, may be null
600      * @param transformer the transformer to use, may be null
601      * @param outputCollection the collection to output into, may not be null
602      * @return the outputCollection with the transformed input added
603      * @throws NullPointerException if the output collection is null
604      */

605     public static Collection JavaDoc collect(Collection JavaDoc inputCollection, final Transformer transformer, final Collection JavaDoc outputCollection) {
606         if (inputCollection != null) {
607             return collect(inputCollection.iterator(), transformer, outputCollection);
608         }
609         return outputCollection;
610     }
611
612     /**
613      * Transforms all elements from the inputIterator with the given transformer
614      * and adds them to the outputCollection.
615      * <p>
616      * If the input iterator or transformer is null, there is no change to the
617      * output collection.
618      *
619      * @param inputIterator the iterator to get the input from, may be null
620      * @param transformer the transformer to use, may be null
621      * @param outputCollection the collection to output into, may not be null
622      * @return the outputCollection with the transformed input added
623      * @throws NullPointerException if the output collection is null
624      */

625     public static Collection JavaDoc collect(Iterator JavaDoc inputIterator, final Transformer transformer, final Collection JavaDoc outputCollection) {
626         if (inputIterator != null && transformer != null) {
627             while (inputIterator.hasNext()) {
628                 Object JavaDoc item = inputIterator.next();
629                 Object JavaDoc value = transformer.transform(item);
630                 outputCollection.add(value);
631             }
632         }
633         return outputCollection;
634     }
635
636     /**
637      * Adds all elements in the iteration to the given collection.
638      *
639      * @param collection the collection to add to
640      * @param iterator the iterator of elements to add, may not be null
641      * @throws NullPointerException if the collection or iterator is null
642      */

643     public static void addAll(Collection JavaDoc collection, Iterator JavaDoc iterator) {
644         while (iterator.hasNext()) {
645             collection.add(iterator.next());
646         }
647     }
648     
649     /**
650      * Adds all elements in the enumeration to the given collection.
651      *
652      * @param collection the collection to add to
653      * @param enumeration the enumeration of elements to add, may not be null
654      * @throws NullPointerException if the collection or enumeration is null
655      */

656     public static void addAll(Collection JavaDoc collection, Enumeration JavaDoc enumeration) {
657         while (enumeration.hasMoreElements()) {
658             collection.add(enumeration.nextElement());
659         }
660     }
661     
662     /**
663      * Adds all elements in the array to the given collection.
664      *
665      * @param collection the collection to add to, may not be null
666      * @param elements the array of elements to add, may not be null
667      * @throws NullPointerException if the collection or array is null
668      */

669     public static void addAll(Collection JavaDoc collection, Object JavaDoc[] elements) {
670         for (int i = 0, size = elements.length; i < size; i++) {
671             collection.add(elements[i]);
672         }
673     }
674     
675     /**
676      * Given an Object, and an index, returns the nth value in the
677      * object.
678      * <ul>
679      * <li>If obj is a Map, returns the nth value from the <b>keySet</b> iterator, unless
680      * the Map contains an Integer key with integer value = idx, in which case the
681      * corresponding map entry value is returned. If idx exceeds the number of entries in
682      * the map, an empty Iterator is returned.
683      * <li>If obj is a List or an array, returns the nth value, throwing IndexOutOfBoundsException,
684      * ArrayIndexOutOfBoundsException, resp. if the nth value does not exist.
685      * <li>If obj is an iterator, enumeration or Collection, returns the nth value from the iterator,
686      * returning an empty Iterator (resp. Enumeration) if the nth value does not exist.
687      * <li>Returns the original obj if it is null or not a Collection or Iterator.
688      * </ul>
689      *
690      * @param obj the object to get an index of, may be null
691      * @param idx the index to get
692      * @throws IndexOutOfBoundsException
693      * @throws ArrayIndexOutOfBoundsException
694      *
695      * @deprecated use {@link #get(Object, int)} instead. Will be removed in v4.0
696      */

697     public static Object JavaDoc index(Object JavaDoc obj, int idx) {
698         return index(obj, new Integer JavaDoc(idx));
699     }
700     
701     /**
702      * Given an Object, and a key (index), returns the value associated with
703      * that key in the Object. The following checks are made:
704      * <ul>
705      * <li>If obj is a Map, use the index as a key to get a value. If no match continue.
706      * <li>Check key is an Integer. If not, return the object passed in.
707      * <li>If obj is a Map, get the nth value from the <b>keySet</b> iterator.
708      * If the Map has fewer than n entries, return an empty Iterator.
709      * <li>If obj is a List or an array, get the nth value, throwing IndexOutOfBoundsException,
710      * ArrayIndexOutOfBoundsException, resp. if the nth value does not exist.
711      * <li>If obj is an iterator, enumeration or Collection, get the nth value from the iterator,
712      * returning an empty Iterator (resp. Enumeration) if the nth value does not exist.
713      * <li>Return the original obj.
714      * </ul>
715      *
716      * @param obj the object to get an index of
717      * @param index the index to get
718      * @return the object at the specified index
719      * @throws IndexOutOfBoundsException
720      * @throws ArrayIndexOutOfBoundsException
721      *
722      * @deprecated use {@link #get(Object, int)} instead. Will be removed in v4.0
723      */

724     public static Object JavaDoc index(Object JavaDoc obj, Object JavaDoc index) {
725         if(obj instanceof Map JavaDoc) {
726             Map JavaDoc map = (Map JavaDoc)obj;
727             if(map.containsKey(index)) {
728                 return map.get(index);
729             }
730         }
731         int idx = -1;
732         if(index instanceof Integer JavaDoc) {
733             idx = ((Integer JavaDoc)index).intValue();
734         }
735         if(idx < 0) {
736             return obj;
737         }
738         else if(obj instanceof Map JavaDoc) {
739             Map JavaDoc map = (Map JavaDoc)obj;
740             Iterator JavaDoc iterator = map.keySet().iterator();
741             return index(iterator, idx);
742         }
743         else if(obj instanceof List JavaDoc) {
744             return ((List JavaDoc)obj).get(idx);
745         }
746         else if(obj instanceof Object JavaDoc[]) {
747             return ((Object JavaDoc[])obj)[idx];
748         }
749         else if(obj instanceof Enumeration JavaDoc) {
750             Enumeration JavaDoc it = (Enumeration JavaDoc)obj;
751             while(it.hasMoreElements()) {
752                 idx--;
753                 if(idx == -1) {
754                     return it.nextElement();
755                 } else {
756                     it.nextElement();
757                 }
758             }
759         }
760         else if(obj instanceof Iterator JavaDoc) {
761             return index((Iterator JavaDoc)obj, idx);
762         }
763         else if(obj instanceof Collection JavaDoc) {
764             Iterator JavaDoc iterator = ((Collection JavaDoc)obj).iterator();
765             return index(iterator, idx);
766         }
767         return obj;
768     }
769
770     private static Object JavaDoc index(Iterator JavaDoc iterator, int idx) {
771         while(iterator.hasNext()) {
772             idx--;
773             if(idx == -1) {
774                 return iterator.next();
775             } else {
776                 iterator.next();
777             }
778         }
779         return iterator;
780     }
781     
782     /**
783      * Returns the <code>index</code>-th value in <code>object</code>, throwing
784      * <code>IndexOutOfBoundsException</code> if there is no such element or
785      * <code>IllegalArgumentException</code> if <code>object</code> is not an
786      * instance of one of the supported types.
787      * <p>
788      * The supported types, and associated semantics are:
789      * <ul>
790      * <li> Map -- the value returned is the <code>Map.Entry</code> in position
791      * <code>index</code> in the map's <code>entrySet</code> iterator,
792      * if there is such an entry.</li>
793      * <li> List -- this method is equivalent to the list's get method.</li>
794      * <li> Array -- the <code>index</code>-th array entry is returned,
795      * if there is such an entry; otherwise an <code>IndexOutOfBoundsException</code>
796      * is thrown.</li>
797      * <li> Collection -- the value returned is the <code>index</code>-th object
798      * returned by the collection's default iterator, if there is such an element.</li>
799      * <li> Iterator or Enumeration -- the value returned is the
800      * <code>index</code>-th object in the Iterator/Enumeration, if there
801      * is such an element. The Iterator/Enumeration is advanced to
802      * <code>index</code> (or to the end, if <code>index</code> exceeds the
803      * number of entries) as a side effect of this method.</li>
804      * </ul>
805      *
806      * @param object the object to get a value from
807      * @param index the index to get
808      * @return the object at the specified index
809      * @throws IndexOutOfBoundsException if the index is invalid
810      * @throws IllegalArgumentException if the object type is invalid
811      */

812     public static Object JavaDoc get(Object JavaDoc object, int index) {
813         if (index < 0) {
814             throw new IndexOutOfBoundsException JavaDoc("Index cannot be negative: " + index);
815         }
816         if (object instanceof Map JavaDoc) {
817             Map JavaDoc map = (Map JavaDoc) object;
818             Iterator JavaDoc iterator = map.entrySet().iterator();
819             return get(iterator, index);
820         } else if (object instanceof List JavaDoc) {
821             return ((List JavaDoc) object).get(index);
822         } else if (object instanceof Object JavaDoc[]) {
823             return ((Object JavaDoc[]) object)[index];
824         } else if (object instanceof Iterator JavaDoc) {
825             Iterator JavaDoc it = (Iterator JavaDoc) object;
826             while (it.hasNext()) {
827                 index--;
828                 if (index == -1) {
829                     return it.next();
830                 } else {
831                     it.next();
832                 }
833             }
834             throw new IndexOutOfBoundsException JavaDoc("Entry does not exist: " + index);
835         } else if (object instanceof Collection JavaDoc) {
836             Iterator JavaDoc iterator = ((Collection JavaDoc) object).iterator();
837             return get(iterator, index);
838         } else if (object instanceof Enumeration JavaDoc) {
839             Enumeration JavaDoc it = (Enumeration JavaDoc) object;
840             while (it.hasMoreElements()) {
841                 index--;
842                 if (index == -1) {
843                     return it.nextElement();
844                 } else {
845                     it.nextElement();
846                 }
847             }
848             throw new IndexOutOfBoundsException JavaDoc("Entry does not exist: " + index);
849         } else if (object == null) {
850             throw new IllegalArgumentException JavaDoc("Unsupported object type: null");
851         } else {
852             try {
853                 return Array.get(object, index);
854             } catch (IllegalArgumentException JavaDoc ex) {
855                 throw new IllegalArgumentException JavaDoc("Unsupported object type: " + object.getClass().getName());
856             }
857         }
858     }
859     
860     /**
861      * Gets the size of the collection/iterator specified.
862      * <p>
863      * This method can handles objects as follows
864      * <ul>
865      * <li>Collection - the collection size
866      * <li>Map - the map size
867      * <li>Array - the array size
868      * <li>Iterator - the number of elements remaining in the iterator
869      * <li>Enumeration - the number of elements remaining in the enumeration
870      * </ul>
871      *
872      * @param object the object to get the size of
873      * @return the size of the specified collection
874      * @throws IllegalArgumentException thrown if object is not recognised or null
875      * @since Commons Collections 3.1
876      */

877     public static int size(Object JavaDoc object) {
878         int total = 0;
879         if (object instanceof Map JavaDoc) {
880             total = ((Map JavaDoc) object).size();
881         } else if (object instanceof Collection JavaDoc) {
882             total = ((Collection JavaDoc) object).size();
883         } else if (object instanceof Object JavaDoc[]) {
884             total = ((Object JavaDoc[]) object).length;
885         } else if (object instanceof Iterator JavaDoc) {
886             Iterator JavaDoc it = (Iterator JavaDoc) object;
887             while (it.hasNext()) {
888                 total++;
889                 it.next();
890             }
891         } else if (object instanceof Enumeration JavaDoc) {
892             Enumeration JavaDoc it = (Enumeration JavaDoc) object;
893             while (it.hasMoreElements()) {
894                 total++;
895                 it.nextElement();
896             }
897         } else if (object == null) {
898             throw new IllegalArgumentException JavaDoc("Unsupported object type: null");
899         } else {
900             try {
901                 total = Array.getLength(object);
902             } catch (IllegalArgumentException JavaDoc ex) {
903                 throw new IllegalArgumentException JavaDoc("Unsupported object type: " + object.getClass().getName());
904             }
905         }
906         return total;
907     }
908     
909     /**
910      * Reverses the order of the given array.
911      *
912      * @param array the array to reverse
913      */

914     public static void reverseArray(Object JavaDoc[] array) {
915         int i = 0;
916         int j = array.length - 1;
917         Object JavaDoc tmp;
918
919         while (j > i) {
920             tmp = array[j];
921             array[j] = array[i];
922             array[i] = tmp;
923             j--;
924             i++;
925         }
926     }
927
928     private static final int getFreq(final Object JavaDoc obj, final Map JavaDoc freqMap) {
929         Integer JavaDoc count = (Integer JavaDoc) freqMap.get(obj);
930         if (count != null) {
931             return count.intValue();
932         }
933         return 0;
934     }
935
936     /**
937      * Returns true if no more elements can be added to the Collection.
938      * <p>
939      * This method uses the {@link BoundedCollection} interface to determine the
940      * full status. If the collection does not implement this interface then
941      * false is returned.
942      * <p>
943      * The collection does not have to implement this interface directly.
944      * If the collection has been decorated using the decorators subpackage
945      * then these will be removed to access the BoundedCollection.
946      *
947      * @param coll the collection to check
948      * @return true if the BoundedCollection is full
949      * @throws NullPointerException if the collection is null
950      */

951     public static boolean isFull(Collection JavaDoc coll) {
952         if (coll == null) {
953             throw new NullPointerException JavaDoc("The collection must not be null");
954         }
955         if (coll instanceof BoundedCollection) {
956             return ((BoundedCollection) coll).isFull();
957         }
958         try {
959             BoundedCollection bcoll = UnmodifiableBoundedCollection.decorateUsing(coll);
960             return bcoll.isFull();
961             
962         } catch (IllegalArgumentException JavaDoc ex) {
963             return false;
964         }
965     }
966
967     /**
968      * Get the maximum number of elements that the Collection can contain.
969      * <p>
970      * This method uses the {@link BoundedCollection} interface to determine the
971      * maximum size. If the collection does not implement this interface then
972      * -1 is returned.
973      * <p>
974      * The collection does not have to implement this interface directly.
975      * If the collection has been decorated using the decorators subpackage
976      * then these will be removed to access the BoundedCollection.
977      *
978      * @param coll the collection to check
979      * @return the maximum size of the BoundedCollection, -1 if no maximum size
980      * @throws NullPointerException if the collection is null
981      */

982     public static int maxSize(Collection JavaDoc coll) {
983         if (coll == null) {
984             throw new NullPointerException JavaDoc("The collection must not be null");
985         }
986         if (coll instanceof BoundedCollection) {
987             return ((BoundedCollection) coll).maxSize();
988         }
989         try {
990             BoundedCollection bcoll = UnmodifiableBoundedCollection.decorateUsing(coll);
991             return bcoll.maxSize();
992             
993         } catch (IllegalArgumentException JavaDoc ex) {
994             return -1;
995         }
996     }
997
998     //-----------------------------------------------------------------------
999
/**
1000     * Returns a synchronized collection backed by the given collection.
1001     * <p>
1002     * You must manually synchronize on the returned buffer's iterator to
1003     * avoid non-deterministic behavior:
1004     *
1005     * <pre>
1006     * Collection c = CollectionUtils.synchronizedCollection(myCollection);
1007     * synchronized (c) {
1008     * Iterator i = c.iterator();
1009     * while (i.hasNext()) {
1010     * process (i.next());
1011     * }
1012     * }
1013     * </pre>
1014     *
1015     * This method uses the implementation in the decorators subpackage.
1016     *
1017     * @param collection the collection to synchronize, must not be null
1018     * @return a synchronized collection backed by the given collection
1019     * @throws IllegalArgumentException if the collection is null
1020     */

1021    public static Collection JavaDoc synchronizedCollection(Collection JavaDoc collection) {
1022        return SynchronizedCollection.decorate(collection);
1023    }
1024
1025    /**
1026     * Returns an unmodifiable collection backed by the given collection.
1027     * <p>
1028     * This method uses the implementation in the decorators subpackage.
1029     *
1030     * @param collection the collection to make unmodifiable, must not be null
1031     * @return an unmodifiable collection backed by the given collection
1032     * @throws IllegalArgumentException if the collection is null
1033     */

1034    public static Collection JavaDoc unmodifiableCollection(Collection JavaDoc collection) {
1035        return UnmodifiableCollection.decorate(collection);
1036    }
1037
1038    /**
1039     * Returns a predicated (validating) collection backed by the given collection.
1040     * <p>
1041     * Only objects that pass the test in the given predicate can be added to the collection.
1042     * Trying to add an invalid object results in an IllegalArgumentException.
1043     * It is important not to use the original collection after invoking this method,
1044     * as it is a backdoor for adding invalid objects.
1045     *
1046     * @param collection the collection to predicate, must not be null
1047     * @param predicate the predicate for the collection, must not be null
1048     * @return a predicated collection backed by the given collection
1049     * @throws IllegalArgumentException if the Collection is null
1050     */

1051    public static Collection JavaDoc predicatedCollection(Collection JavaDoc collection, Predicate predicate) {
1052        return PredicatedCollection.decorate(collection, predicate);
1053    }
1054
1055    /**
1056     * Returns a typed collection backed by the given collection.
1057     * <p>
1058     * Only objects of the specified type can be added to the collection.
1059     *
1060     * @param collection the collection to limit to a specific type, must not be null
1061     * @param type the type of objects which may be added to the collection
1062     * @return a typed collection backed by the specified collection
1063     */

1064    public static Collection JavaDoc typedCollection(Collection JavaDoc collection, Class JavaDoc type) {
1065        return TypedCollection.decorate(collection, type);
1066    }
1067    
1068    /**
1069     * Returns a transformed bag backed by the given collection.
1070     * <p>
1071     * Each object is passed through the transformer as it is added to the
1072     * Collection. It is important not to use the original collection after invoking this
1073     * method, as it is a backdoor for adding untransformed objects.
1074     *
1075     * @param collection the collection to predicate, must not be null
1076     * @param transformer the transformer for the collection, must not be null
1077     * @return a transformed collection backed by the given collection
1078     * @throws IllegalArgumentException if the Collection or Transformer is null
1079     */

1080    public static Collection JavaDoc transformedCollection(Collection JavaDoc collection, Transformer transformer) {
1081        return TransformedCollection.decorate(collection, transformer);
1082    }
1083    
1084}
1085
Popular Tags