<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.2</version>
</dependency>
package org.apache.commons.collections;
public class ListUtils {
/**
* 不可变的空集合
*/
public static final List EMPTY_LIST = Collections.EMPTY_LIST;
public ListUtils() {
}
/**
* 返回两个集合共有的元素
*/
public static List intersection(final List list1, final List list2) {
final ArrayList result = new ArrayList();
final Iterator iterator = list2.iterator();
while (iterator.hasNext()) {
final Object o = iterator.next();
if (list1.contains(o)) {
result.add(o);
}
}
return result;
}
/**
* 从第一个集合中去掉第二个集合中包含的元素
*/
public static List subtract(final List list1, final List list2) {
final ArrayList result = new ArrayList(list1);
final Iterator iterator = list2.iterator();
while (iterator.hasNext()) {
result.remove(iterator.next());
}
return result;
}
/**
* 取第一个集合和第二个集合所有的元素,并去除两个集合中重复的元素
*/
public static List sum(final List list1, final List list2) {
return subtract(union(list1, list2), intersection(list1, list2));
}
/**
* 将两个集合合并成一个新的集合
*/
public static List union(final List list1, final List list2) {
final ArrayList result = new ArrayList(list1);
result.addAll(list2);
return result;
}
/**
* 判断两个集合是否相等
*/
public static boolean isEqualList(final Collection list1, final Collection list2) {
if (list1 == list2) {
return true;
}
if (list1 == null || list2 == null || list1.size() != list2.size()) {
return false;
}
Iterator it1 = list1.iterator();
Iterator it2 = list2.iterator();
Object obj1 = null;
Object obj2 = null;
while (it1.hasNext() && it2.hasNext()) {
obj1 = it1.next();
obj2 = it2.next();
if (!(obj1 == null ? obj2 == null : obj1.equals(obj2))) {
return false;
}
}
return !(it1.hasNext() || it2.hasNext());
}
/**
* 生成一个集合的hashcode
*/
public static int hashCodeForList(final Collection list) {
if (list == null) {
return 0;
}
int hashCode = 1;
Iterator it = list.iterator();
Object obj = null;
while (it.hasNext()) {
obj = it.next();
hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
}
return hashCode;
}
/**
* 返回第一个集合中的元素在第一个集合中存在的一个新集合
*/
public static List retainAll(Collection collection, Collection retain) {
List list = new ArrayList(Math.min(collection.size(), retain.size()));
for (Iterator iter = collection.iterator(); iter.hasNext();) {
Object obj = iter.next();
if (retain.contains(obj)) {
list.add(obj);
}
}
return list;
}
/**
* 返回从第一个集合中移除掉remove集合中包含的元素的新集合
*/
public static List removeAll(Collection collection, Collection remove) {
List list = new ArrayList();
for (Iterator iter = collection.iterator(); iter.hasNext();) {
Object obj = iter.next();
if (remove.contains(obj) == false) {
list.add(obj);
}
}
return list;
}
/**
* 返回一个同步的List
*/
public static List synchronizedList(List list) {
return SynchronizedList.decorate(list);
}
/**
* 返回一个不可修改的List
*/
public static List unmodifiableList(List list) {
return UnmodifiableList.decorate(list);
}
/**
* 返回一个有断言功能List,传入的Predicate在执行add的时候对添加的元素进行校验,校验不通过则抛出IllegalArgumentException
*/
public static List predicatedList(List list, Predicate predicate) {
return PredicatedList.decorate(list, predicate);
}
/**
* 返回一个可以添加指定元素类型的List,其他同predicatedList方法
*/
public static List typedList(List list, Class type) {
return TypedList.decorate(list, type);
}
/**
* 返回一个修饰后的列表,在add和set的时候对元素进行转换后再执行相关操作
*/
public static List transformedList(List list, Transformer transformer) {
return TransformedList.decorate(list, transformer);
}
/**
* 返回一个LazyList,当调用get方法时,如果索引超出列表长度,列表会自动增长(可以通过一个工厂获得超出索引位置的值)
* LazyList和GrowthList都可以实现对修饰的列表进行增长,但是LazyList发生在get时候,而GrowthList发生在set和add时候。
*/
public static List lazyList(List list, Factory factory) {
return LazyList.decorate(list, factory);
}
/**
* 返回一个FixedSizeList,修饰一个防止添加/删除的固定大小的列表。add/remove/clear/retain操作是不被支持的
*/
public static List fixedSizeList(List list) {
return FixedSizeList.decorate(list);
}
}
CursorableLinkedList是List的一种实现,提供了一个列表迭代器并且允许修改列表。CursorableLinkedList支持所有可选列表的操作。它继承自AbstractLinkedList,提供了stack/queue/dequeue的操作。这个类的主要功能是能够在同一时间修改列表和迭代器。listIterator()和cursor()方法都提供了访问一个继承自ListIterator的Cursor实例。游标允许更改列表时并发修改迭代器。需要注意的是,iterator()方法和子列表不会提供这种光标行为。CursorableLinkedList不是线程同步的。
public class CursorableLinkedListTest
{
@Test
public void test()
{
CursorableLinkedList linkedList = new CursorableLinkedList();
linkedList.add("center");
linkedList.addFirst("first");
linkedList.addLast("last");
System.out.println(linkedList);
Cursor cursor = linkedList.cursor();
if (cursor.hasNext())
{
Object o = cursor.next();
System.out.println("使用游标移除元素:" + o);
cursor.remove();
}
cursor.close();
System.out.println(linkedList);
Iterator<?> iterator = linkedList.iterator();
if (iterator.hasNext())
{
Object o = iterator.next();
System.out.println("使用迭代器移除元素:" + o);
iterator.remove();
}
System.out.println(linkedList);
}
}
package org.apache.commons.collections;
public class CollectionUtils {
private static Integer INTEGER_ONE = new Integer(1);
/**
* 一个不可修改的List
*/
public static final Collection EMPTY_COLLECTION = UnmodifiableCollection.decorate(new ArrayList());
public CollectionUtils() {
}
/**
* 两个集合的并集,且将a和b中包含的相同元素去重。如果a或者b中包含多个相同的元素,则取重复次数多的那个集合中的次数
*/
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<m;i++) {
list.add(obj);
}
}
return list;
}
/**
* 取两个集合中的交集
*/
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<m;i++) {
list.add(obj);
}
}
return list;
}
/**
* 取两个集合中的差集
*/
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<m;i++) {
list.add(obj);
}
}
return list;
}
/**
* 从集合a中移除集合b中的元素
*/
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());
}
return list;
}
/**
* 判断集合1和集合2是否包含相同的元素
*/
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())) {
return true;
}
}
} else {
for (Iterator it = coll2.iterator(); it.hasNext();) {
if (coll1.contains(it.next())) {
return true;
}
}
}
return false;
}
/**
* 统计集合中包含的元素的基数,并用Map结构存储,key元素值,value为key出现的次数
*/
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));
if (c == null) {
count.put(obj,INTEGER_ONE);
} else {
count.put(obj,new Integer(c.intValue() + 1));
}
}
return count;
}
/**
* 判断集合a是否是集合b的子集
*/
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)) {
return false;
}
}
return true;
}
/**
* 判断集合a是否是集合b的完全子集
*/
public static boolean isProperSubCollection(final Collection a, final Collection b) {
return (a.size() < b.size()) && CollectionUtils.isSubCollection(a,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()) {
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;
}
}
}
/**
* 返回某个元素在集合中的基数
*/
public static int cardinality(Object obj, final Collection coll) {
if (coll instanceof Set) {
return (coll.contains(obj) ? 1 : 0);
}
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) {
count++;
}
}
} else {
for (Iterator it = coll.iterator();it.hasNext();) {
if (obj.equals(it.next())) {
count++;
}
}
}
return count;
}
/**
* 返回集合中和断言匹配的第一个元素
*/
public static Object find(Collection collection, Predicate predicate) {
if (collection != null && predicate != null) {
for (Iterator iter = collection.iterator(); iter.hasNext();) {
Object item = iter.next();
if (predicate.evaluate(item)) {
return item;
}
}
}
return null;
}
/**
* 对集合中的每个元素执行闭包操作
*/
public static void forAllDo(Collection collection, Closure closure) {
if (collection != null && closure != null) {
for (Iterator it = collection.iterator(); it.hasNext();) {
closure.execute(it.next());
}
}
}
/**
* 将集合中与断言不匹配的元素移除
*/
public static void filter(Collection collection, Predicate predicate) {
if (collection != null && predicate != null) {
for (Iterator it = collection.iterator(); it.hasNext();) {
if (predicate.evaluate(it.next()) == false) {
it.remove();
}
}
}
}
/**
* 将集合中的元素按照输入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();) {
it.set(transformer.transform(it.next()));
}
} else {
Collection resultCollection = collect(collection, transformer);
collection.clear();
collection.addAll(resultCollection);
}
}
}
/**
* 统计集合中和断言匹配的元素的个数
*/
public static int countMatches(Collection inputCollection, Predicate predicate) {
int count = 0;
if (inputCollection != null && predicate != null) {
for (Iterator it = inputCollection.iterator(); it.hasNext();) {
if (predicate.evaluate(it.next())) {
count++;
}
}
}
return count;
}
/**
* 判断集中是否存在与断言匹配的元素
*/
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())) {
return true;
}
}
}
return false;
}
/**
* 提取集合中与断言匹配的元素加入到新集合中
*/
public static Collection select(Collection inputCollection, Predicate predicate) {
ArrayList answer = new ArrayList(inputCollection.size());
select(inputCollection, predicate, answer);
return answer;
}
/**
* Selects all elements from input collection which match the given predicate
* and adds them to outputCollection.
* <p>
* 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
*/
public static void select(Collection inputCollection, Predicate predicate, Collection outputCollection) {
if (inputCollection != null && predicate != null) {
for (Iterator iter = inputCollection.iterator(); iter.hasNext();) {
Object item = iter.next();
if (predicate.evaluate(item)) {
outputCollection.add(item);
}
}
}
}
/**
* Selects all elements from inputCollection which don't match the given predicate
* into an output collection.
* <p>
* If the input predicate is <code>null</code>, 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 <b>not</b> matching the predicate (new list)
* @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;
}
/**
* Selects all elements from inputCollection which don't match the given predicate
* and adds them to outputCollection.
* <p>
* If the input predicate is <code>null</code>, no elements are added to <code>outputCollection</code>.
*
* @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
*/
public static void selectRejected(Collection inputCollection, Predicate predicate, Collection outputCollection) {
if (inputCollection != null && predicate != null) {
for (Iterator iter = inputCollection.iterator(); iter.hasNext();) {
Object item = iter.next();
if (predicate.evaluate(item) == false) {
outputCollection.add(item);
}
}
}
}
/**
* Returns a new Collection consisting of the elements of inputCollection transformed
* by the given transformer.
* <p>
* 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
* @return the transformed result (new list)
* @throws NullPointerException if the input collection is null
*/
public static Collection collect(Collection inputCollection, Transformer transformer) {
ArrayList answer = new ArrayList(inputCollection.size());
collect(inputCollection, transformer, answer);
return answer;
}
/**
* Transforms all elements from the inputIterator with the given transformer
* and adds them to the outputCollection.
* <p>
* 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
* @return the transformed result (new list)
*/
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
* and adds them to the outputCollection.
* <p>
* 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
* @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) {
if (inputCollection != null) {
return collect(inputCollection.iterator(), transformer, outputCollection);
}
return outputCollection;
}
/**
* Transforms all elements from the inputIterator with the given transformer
* and adds them to the outputCollection.
* <p>
* 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
* @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) {
if (inputIterator != null && transformer != null) {
while (inputIterator.hasNext()) {
Object item = inputIterator.next();
Object value = transformer.transform(item);
outputCollection.add(value);
}
}
return outputCollection;
}
//-----------------------------------------------------------------------
/**
* 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) {
return (object == null ? false : collection.add(object));
}
/**
* 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
*/
public static void addAll(Collection collection, Iterator iterator) {
while (iterator.hasNext()) {
collection.add(iterator.next());
}
}
/**
* 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) {
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
*/
public static void addAll(Collection collection, Object[] 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.
* <ul>
* <li>If obj is a Map, returns the nth value from the <b>keySet</b> 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.
* <li>If obj is a List or an array, returns the nth value, throwing IndexOutOfBoundsException,
* ArrayIndexOutOfBoundsException, resp. if the nth value does not exist.
* <li>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.
* <li>Returns the original obj if it is null or not a Collection or Iterator.
* </ul>
*
* @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:
* <ul>
* <li>If obj is a Map, use the index as a key to get a value. If no match continue.
* <li>Check key is an Integer. If not, return the object passed in.
* <li>If obj is a Map, get the nth value from the <b>keySet</b> iterator.
* If the Map has fewer than n entries, return an empty Iterator.
* <li>If obj is a List or an array, get the nth value, throwing IndexOutOfBoundsException,
* ArrayIndexOutOfBoundsException, resp. if the nth value does not exist.
* <li>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.
* <li>Return the original obj.
* </ul>
*
* @param obj the object to get an index of
* @param index the index to get
* @return the object at the specified index
* @throws IndexOutOfBoundsException
* @throws ArrayIndexOutOfBoundsException
*
* @deprecated use {@link #get(Object, int)} instead. Will be removed in v4.0
*/
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();
}
}
}
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();
}
}
return iterator;
}
/**
* Returns the <code>index</code>-th value in <code>object</code>, throwing
* <code>IndexOutOfBoundsException</code> if there is no such element or
* <code>IllegalArgumentException</code> if <code>object</code> is not an
* instance of one of the supported types.
* <p>
* The supported types, and associated semantics are:
* <ul>
* <li> Map -- the value returned is the <code>Map.Entry</code> in position
* <code>index</code> in the map's <code>entrySet</code> iterator,
* if there is such an entry.</li>
* <li> List -- this method is equivalent to the list's get method.</li>
* <li> Array -- the <code>index</code>-th array entry is returned,
* if there is such an entry; otherwise an <code>IndexOutOfBoundsException</code>
* is thrown.</li>
* <li> Collection -- the value returned is the <code>index</code>-th object
* returned by the collection's default iterator, if there is such an element.</li>
* <li> Iterator or Enumeration -- the value returned is the
* <code>index</code>-th object in the Iterator/Enumeration, if there
* is such an element. The Iterator/Enumeration is advanced to
* <code>index</code> (or to the end, if <code>index</code> exceeds the
* number of entries) as a side effect of this method.</li>
* </ul>
*
* @param object the object to get a value from
* @param index the index to get
* @return the object at the specified index
* @throws IndexOutOfBoundsException if the index is invalid
* @throws IllegalArgumentException if the object type is invalid
*/
public static Object get(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);
} else if (object instanceof Object[]) {
return ((Object[]) object)[index];
} else if (object instanceof Iterator) {
Iterator it = (Iterator) object;
while (it.hasNext()) {
index--;
if (index == -1) {
return it.next();
} else {
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;
while (it.hasMoreElements()) {
index--;
if (index == -1) {
return it.nextElement();
} else {
it.nextElement();
}
}
throw new IndexOutOfBoundsException("Entry does not exist: " + index);
} else if (object == null) {
throw new IllegalArgumentException("Unsupported object type: null");
} else {
try {
return Array.get(object, index);
} catch (IllegalArgumentException ex) {
throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName());
}
}
}
/**
* Gets the size of the collection/iterator specified.
* <p>
* This method can handles objects as follows
* <ul>
* <li>Collection - the collection size
* <li>Map - the map size
* <li>Array - the array size
* <li>Iterator - the number of elements remaining in the iterator
* <li>Enumeration - the number of elements remaining in the enumeration
* </ul>
*
* @param object the object to get the size of
* @return the size of the specified collection
* @throws IllegalArgumentException thrown if object is not recognised or null
* @since Commons Collections 3.1
*/
public static int size(Object object) {
int total = 0;
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;
while (it.hasNext()) {
total++;
it.next();
}
} else if (object instanceof Enumeration) {
Enumeration it = (Enumeration) object;
while (it.hasMoreElements()) {
total++;
it.nextElement();
}
} else if (object == null) {
throw new IllegalArgumentException("Unsupported object type: null");
} else {
try {
total = Array.getLength(object);
} catch (IllegalArgumentException ex) {
throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName());
}
}
return total;
}
/**
* Checks if the specified collection/array/iterator is empty.
* <p>
* This method can handles objects as follows
* <ul>
* <li>Collection - via collection isEmpty
* <li>Map - via map isEmpty
* <li>Array - using array size
* <li>Iterator - via hasNext
* <li>Enumeration - via hasMoreElements
* </ul>
* <p>
* Note: This method is named to avoid clashing with
* {@link #isEmpty(Collection)}.
*
* @param object the object to get the size of, not null
* @return true if empty
* @throws IllegalArgumentException thrown if object is not recognised or null
* @since Commons Collections 3.2
*/
public static boolean sizeIsEmpty(Object object) {
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 == null) {
throw new IllegalArgumentException("Unsupported object type: null");
} else {
try {
return Array.getLength(object) == 0;
} catch (IllegalArgumentException ex) {
throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName());
}
}
}
//-----------------------------------------------------------------------
/**
* Null-safe check if the specified collection is empty.
* <p>
* 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) {
return (coll == null || coll.isEmpty());
}
/**
* Null-safe check if the specified collection is not empty.
* <p>
* 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);
}
//-----------------------------------------------------------------------
/**
* Reverses the order of the given array.
*
* @param array the array to reverse
*/
public static void reverseArray(Object[] array) {
int i = 0;
int j = array.length - 1;
Object tmp;
while (j > i) {
tmp = array[j];
array[j] = array[i];
array[i] = tmp;
j--;
i++;
}
}
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.
* <p>
* This method uses the {@link BoundedCollection} interface to determine the
* full status. If the collection does not implement this interface then
* false is returned.
* <p>
* The collection does not have to implement this interface directly.
* If the collection has been decorated using the decorators subpackage
* then these will be removed to access the BoundedCollection.
*
* @param coll the collection to check
* @return true if the BoundedCollection is full
* @throws NullPointerException if the collection is null
*/
public static boolean isFull(Collection coll) {
if (coll == null) {
throw new NullPointerException("The collection must not be null");
}
if (coll instanceof BoundedCollection) {
return ((BoundedCollection) coll).isFull();
}
try {
BoundedCollection bcoll = UnmodifiableBoundedCollection.decorateUsing(coll);
return bcoll.isFull();
} catch (IllegalArgumentException ex) {
return false;
}
}
/**
* Get the maximum number of elements that the Collection can contain.
* <p>
* This method uses the {@link BoundedCollection} interface to determine the
* maximum size. If the collection does not implement this interface then
* -1 is returned.
* <p>
* The collection does not have to implement this interface directly.
* If the collection has been decorated using the decorators subpackage
* then these will be removed to access the BoundedCollection.
*
* @param coll the collection to check
* @return the maximum size of the BoundedCollection, -1 if no maximum size
* @throws NullPointerException if the collection is null
*/
public static int maxSize(Collection coll) {
if (coll == null) {
throw new NullPointerException("The collection must not be null");
}
if (coll instanceof BoundedCollection) {
return ((BoundedCollection) coll).maxSize();
}
try {
BoundedCollection bcoll = UnmodifiableBoundedCollection.decorateUsing(coll);
return bcoll.maxSize();
} catch (IllegalArgumentException ex) {
return -1;
}
}
//-----------------------------------------------------------------------
/**
* Returns a collection containing all the elements in <code>collection</code>
* that are also in <code>retain</code>. The cardinality of an element <code>e</code>
* in the returned collection is the same as the cardinality of <code>e</code>
* in <code>collection</code> unless <code>retain</code> does not contain <code>e</code>, in which
* case the cardinality is zero. This method is useful if you do not wish to modify
* the collection <code>c</code> and thus cannot call <code>c.retainAll(retain);</code>.
*
* @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 <code>Collection</code> containing all the elements of <code>collection</code>
* that occur at least once in <code>retain</code>.
* @throws NullPointerException if either parameter is null
* @since Commons Collections 3.2
*/
public static Collection retainAll(Collection collection, Collection retain) {
return ListUtils.retainAll(collection, retain);
}
/**
* Removes the elements in <code>remove</code> from <code>collection</code>. That is, this
* method returns a collection containing all the elements in <code>c</code>
* that are not in <code>remove</code>. The cardinality of an element <code>e</code>
* in the returned collection is the same as the cardinality of <code>e</code>
* in <code>collection</code> unless <code>remove</code> contains <code>e</code>, in which
* case the cardinality is zero. This method is useful if you do not wish to modify
* the collection <code>c</code> and thus cannot call <code>collection.removeAll(remove);</code>.
*
* @param collection the collection from which items are removed (in the returned collection)
* @param remove the items to be removed from the returned <code>collection</code>
* @return a <code>Collection</code> containing all the elements of <code>collection</code> except
* any elements that also occur in <code>remove</code>.
* @throws NullPointerException if either parameter is null
* @since Commons Collections 3.2
*/
public static Collection removeAll(Collection collection, Collection remove) {
return ListUtils.removeAll(collection, remove);
}
//-----------------------------------------------------------------------
/**
* Returns a synchronized collection backed by the given collection.
* <p>
* You must manually synchronize on the returned buffer's iterator to
* avoid non-deterministic behavior:
*
* <pre>
* Collection c = CollectionUtils.synchronizedCollection(myCollection);
* synchronized (c) {
* Iterator i = c.iterator();
* while (i.hasNext()) {
* process (i.next());
* }
* }
* </pre>
*
* 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) {
return SynchronizedCollection.decorate(collection);
}
/**
* Returns an unmodifiable collection backed by the given collection.
* <p>
* This method uses the implementation in the decorators subpackage.
*
* @param collection the collection to make unmodifiable, must not be null
* @return an unmodifiable collection backed by the given collection
* @throws IllegalArgumentException if the collection is null
*/
public static Collection unmodifiableCollection(Collection collection) {
return UnmodifiableCollection.decorate(collection);
}
/**
* Returns a predicated (validating) collection backed by the given collection.
* <p>
* Only objects that pass the test in the given predicate can be added to the collection.
* Trying to add an invalid object results in an IllegalArgumentException.
* It is important not to use the original collection after invoking this method,
* as it is a backdoor for adding invalid objects.
*
* @param collection the collection to predicate, must not be null
* @param predicate the predicate for the collection, must not be null
* @return a predicated collection backed by the given collection
* @throws IllegalArgumentException if the Collection is null
*/
public static Collection predicatedCollection(Collection collection, Predicate predicate) {
return PredicatedCollection.decorate(collection, predicate);
}
/**
* Returns a typed collection backed by the given collection.
* <p>
* 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.
* <p>
* Each object is passed through the transformer as it is added to the
* Collection. It is important not to use the original collection after invoking this
* method, as it is a backdoor for adding untransformed objects.
*
* @param collection the collection to predicate, must not be null
* @param transformer the transformer for the collection, must not be null
* @return a transformed collection backed by the given collection
* @throws IllegalArgumentException if the Collection or Transformer is null
*/
public static Collection transformedCollection(Collection collection, Transformer transformer) {
return TransformedCollection.decorate(collection, transformer);
}
}