
ext.test4j.apache.commons.collections.CollectionUtils Maven / Gradle / Ivy
/*
* Copyright 1999-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ext.test4j.apache.commons.collections;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* A set of {@link Collection} related utility methods.
*
* @since 1.0
* @author Rodney Waldhoff
* @author Paul Jack
* @author Stephen Colebourne
* @author Steve Downey
* @version $Revision: 1.18.2.2 $ $Date: 2004/05/22 12:14:02 $
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public class CollectionUtils {
/**
* Please don't ever instantiate a CollectionUtils
.
*/
public CollectionUtils() {
}
/**
* 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.
*
* @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 < m; i++) {
list.add(obj);
}
}
return list;
}
/**
* 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.
*
* @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 < m; i++) {
list.add(obj);
}
}
return 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
* 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)}).
*/
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;
}
/**
* Returns a {@link Collection} containing a - b. The
* cardinality of each element e in the returned {@link Collection}
* will be the cardinality of e in a minus the cardinality of
* e in b, or zero, whichever is greater.
*
* @see Collection#removeAll
*/
public static Collection subtract(final Collection a, final Collection b) {
ArrayList list = new ArrayList(a);
Iterator it = b.iterator();
while (it.hasNext()) {
list.remove(it.next());
}
return list;
}
/**
* Returns true
iff some element of a is also an element
* of b (or, equivalently, if some element of b is also an
* element of a). In other words, this method returns
* true
iff the {@link #intersection} of a and b
* is not empty.
*
* @since 2.1
* @param a
* a non-null
Collection
* @param b
* a non-null
Collection
* @return true
iff the intersection of a and b
* is non-empty
* @see #intersection
*/
public static boolean containsAny(final Collection a, final Collection b) {
// TO DO: we may be able to optimize this by ensuring either a or b
// is the larger of the two Collections, but I'm not sure which.
for (Iterator iter = a.iterator(); iter.hasNext();) {
if (b.contains(iter.next())) {
return true;
}
}
return false;
}
/**
* Returns a {@link Map} mapping each unique element in the given
* {@link Collection} to an {@link Integer} representing the number of
* occurances of that element in the {@link Collection}. An entry that maps
* to null indicates that the element does not appear in the given
* {@link Collection}.
*/
public static Map getCardinalityMap(final Collection col) {
HashMap count = new HashMap();
Iterator it = col.iterator();
while (it.hasNext()) {
Object obj = it.next();
Integer c = (Integer) (count.get(obj));
if (null == c) {
count.put(obj, new Integer(1));
} else {
count.put(obj, new Integer(c.intValue() + 1));
}
}
return count;
}
/**
* 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.
*
* @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)) {
return false;
}
}
return true;
}
/**
* Returns true iff the given {@link Collection}s contain exactly
* the same elements with exactly the same cardinality.
*
* That is, iff the cardinality of e in a is equal to the
* cardinality of e in b, for each element e in
* a or 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;
}
}
}
/**
* Returns the number of occurrences of obj in col.
*/
public static int cardinality(Object obj, final Collection col) {
int count = 0;
Iterator it = col.iterator();
while (it.hasNext()) {
Object elt = it.next();
if ((null == obj && null == elt) || obj.equals(elt)) {
count++;
}
}
return count;
}
/**
* 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 and uses set(), however it adapts for all
* Collections that support clear() and addAll().
*
* 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
*/
public static void transform(Collection collection, Transformer transformer) {
if (collection != null && transformer != null) {
if (collection instanceof List) {
List list = (List) collection;
for (ListIterator iter = list.listIterator(); iter.hasNext();) {
Object element = iter.next();
iter.set(transformer.transform(element));
}
} else {
Collection resultCollection = collect(collection, transformer);
collection.clear();
collection.addAll(resultCollection);
}
}
}
/**
* Transforms all elements from inputCollection with the given transformer
* and adds them to the outputCollection.
*
* If the input transfomer 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.
*
* If the input iterator or transfomer 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.
*
* If the input collection or transfomer 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.
*
* If the input iterator or transfomer 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 all elements in the iteration to the given collection.
*
* @param collection
* the collection to add to
* @param iterator
* the iterator of elements to add, may 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
* @param enumeration
* the enumeration of elements to add, may 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
* @param elements
* the array of elements to add, may 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, it will get the nth value in the object.
*
* - If obj is a Map, get the nth value from the key iterator.
*
- If obj is a List or an array, get the nth value.
*
- If obj is an iterator, enumeration or Collection, get the nth value
* from the iterator.
*
- Return the original obj.
*
*
* @param obj
* the object to get an index of
* @param index
* the index to get
* @throws IndexOutOfBoundsException
* @throws NoSuchElementException
*/
public static Object index(Object obj, int idx) {
return index(obj, new Integer(idx));
}
/**
* Given an Object, and a key (index), it will get 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 key iterator.
*
- If obj is a List or an array, get the nth value.
*
- If obj is an iterator, enumeration or Collection, get the nth value
* from the iterator.
*
- Return the original obj.
*
*
* @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 NoSuchElementException
*/
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 enumeration = (Enumeration) obj;
while (enumeration.hasMoreElements()) {
idx--;
if (idx == -1) {
return enumeration.nextElement();
} else {
enumeration.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;
}
/** Reverses the order of the given array */
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) {
try {
return ((Integer) (freqMap.get(obj))).intValue();
} catch (NullPointerException e) {
// ignored
} catch (NoSuchElementException e) {
// ignored
}
return 0;
}
/**
* Base class for collection decorators. I decided to do it this way because
* it seemed to result in the most reuse.
*
* Inner class tree looks like:
*
*
* CollectionWrapper
* PredicatedCollection
* PredicatedSet
* PredicatedList
* PredicatedBag
* PredicatedBuffer
* UnmodifiableCollection
* UnmodifiableBag
* UnmodifiableBuffer
* LazyCollection
* LazyList
* LazyBag
* SynchronizedCollection
* SynchronizedBuffer
* SynchronizedBag
* SynchronizedBuffer
*
*/
static class CollectionWrapper implements Collection {
protected final Collection collection;
public CollectionWrapper(Collection collection) {
if (collection == null) {
throw new IllegalArgumentException("Collection must not be null");
}
this.collection = collection;
}
public int size() {
return collection.size();
}
public boolean isEmpty() {
return collection.isEmpty();
}
public boolean contains(Object o) {
return collection.contains(o);
}
public Iterator iterator() {
return collection.iterator();
}
public Object[] toArray() {
return collection.toArray();
}
public Object[] toArray(Object[] o) {
return collection.toArray(o);
}
public boolean add(Object o) {
return collection.add(o);
}
public boolean remove(Object o) {
return collection.remove(o);
}
public boolean containsAll(Collection c2) {
return collection.containsAll(c2);
}
public boolean addAll(Collection c2) {
return collection.addAll(c2);
}
public boolean removeAll(Collection c2) {
return collection.removeAll(c2);
}
public boolean retainAll(Collection c2) {
return collection.retainAll(c2);
}
public void clear() {
collection.clear();
}
public boolean equals(Object o) {
if (o == this)
return true;
return collection.equals(o);
}
public int hashCode() {
return collection.hashCode();
}
public String toString() {
return collection.toString();
}
}
static class UnmodifiableCollection extends CollectionWrapper {
public UnmodifiableCollection(Collection c) {
super(c);
}
public boolean add(Object o) {
throw new UnsupportedOperationException();
}
public boolean addAll(Collection c) {
throw new UnsupportedOperationException();
}
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
public boolean removeAll(Collection c) {
throw new UnsupportedOperationException();
}
public boolean retainAll(Collection c) {
throw new UnsupportedOperationException();
}
public void clear() {
throw new UnsupportedOperationException();
}
public Iterator iterator() {
return new UnmodifiableIterator(collection.iterator());
}
}
static class SynchronizedCollection {
protected final Collection collection;
public SynchronizedCollection(Collection collection) {
if (collection == null) {
throw new IllegalArgumentException("Collection must not be null");
}
this.collection = collection;
}
public synchronized int size() {
return collection.size();
}
public synchronized boolean isEmpty() {
return collection.isEmpty();
}
public synchronized boolean contains(Object o) {
return collection.contains(o);
}
public Iterator iterator() {
return collection.iterator();
}
public synchronized Object[] toArray() {
return collection.toArray();
}
public synchronized Object[] toArray(Object[] o) {
return collection.toArray(o);
}
public synchronized boolean add(Object o) {
return collection.add(o);
}
public synchronized boolean remove(Object o) {
return collection.remove(o);
}
public synchronized boolean containsAll(Collection c2) {
return collection.containsAll(c2);
}
public synchronized boolean addAll(Collection c2) {
return collection.addAll(c2);
}
public synchronized boolean removeAll(Collection c2) {
return collection.removeAll(c2);
}
public synchronized boolean retainAll(Collection c2) {
return collection.retainAll(c2);
}
public synchronized void clear() {
collection.clear();
}
public synchronized boolean equals(Object o) {
return collection.equals(o);
}
public synchronized int hashCode() {
return collection.hashCode();
}
public synchronized String toString() {
return collection.toString();
}
}
static class UnmodifiableIterator implements Iterator {
protected final Iterator iterator;
public UnmodifiableIterator(Iterator iterator) {
if (iterator == null) {
throw new IllegalArgumentException("Iterator must not be null");
}
this.iterator = iterator;
}
public boolean hasNext() {
return iterator.hasNext();
}
public Object next() {
return iterator.next();
}
public void remove() {
throw new UnsupportedOperationException();
}
}
}