[COLLECTIONS-446] Added method isEqualCollection(Collection, Collection, Equator) to CollectionUtils.

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/collections/trunk@1453012 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Thomas Neidhart 2013-03-05 21:29:50 +00:00
parent 5f2a8837c0
commit 41f5524e92
3 changed files with 108 additions and 0 deletions

View File

@ -22,6 +22,9 @@
<body>
<release version="4.0" date="TBA" description="Next release">
<action issue="COLLECTIONS-446" dev="tn" type="add" due-to="Matt Lachman">
Added method "CollectionUtils#isEqualCollection(Collection, Collection, Equator)".
</action>
<action issue="COLLECTIONS-447" dev="tn" type="fix" due-to="Jeffrey Barnes">
Tree traversal with a TreeListIterator will not be affected anymore by
the removal of an element directly after a call to previous().

View File

@ -34,6 +34,7 @@ import org.apache.commons.collections.collection.SynchronizedCollection;
import org.apache.commons.collections.collection.TransformedCollection;
import org.apache.commons.collections.collection.UnmodifiableBoundedCollection;
import org.apache.commons.collections.collection.UnmodifiableCollection;
import org.apache.commons.collections.functors.Equator;
import org.apache.commons.collections.functors.TruePredicate;
/**
@ -522,6 +523,78 @@ public class CollectionUtils {
return true;
}
/**
* Returns <tt>true</tt> iff the given {@link Collection}s contain
* exactly the same elements with exactly the same cardinalities.
* <p>
* That is, iff the cardinality of <i>e</i> in <i>a</i> is
* equal to the cardinality of <i>e</i> in <i>b</i>,
* for each element <i>e</i> in <i>a</i> or <i>b</i>.
*
* @param a the first collection, must not be null
* @param b the second collection, must not be null
* @param equator the Equator used for testing equality
* @return <code>true</code> iff the collections contain the same elements with the same cardinalities.
* @throws IllegalArgumentException if the equator is null
* @since 4.0
*/
@SuppressWarnings({ "unchecked", "rawtypes" }) // we don't know the types due to wildcards in the signature
public static boolean isEqualCollection(final Collection<?> a, final Collection<?> b, final Equator<?> equator) {
if (equator == null) {
throw new IllegalArgumentException("equator may not be null");
}
if(a.size() != b.size()) {
return false;
}
final Transformer transformer = new Transformer() {
public EquatorWrapper<?> transform(Object input) {
return new EquatorWrapper(equator, input);
}
};
return isEqualCollection(collect(a, transformer), collect(b, transformer));
}
/**
* Wraps another object and uses the provided Equator to implement
* {@link #equals(Object)} and {@link #hashCode()}.
* <p>
* This class can be used to store objects into a Map.
*
* @param <O> the element type
* @since 4.0
*/
private static class EquatorWrapper<O> {
private final Equator<O> equator;
private final O object;
public EquatorWrapper(final Equator<O> equator, final O object) {
this.equator = equator;
this.object = object;
}
public O getObject() {
return object;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof EquatorWrapper)) {
return false;
}
@SuppressWarnings("unchecked")
EquatorWrapper<O> otherObj = (EquatorWrapper<O>) obj;
return equator.equate(object, otherObj.getObject());
}
@Override
public int hashCode() {
return equator.hash(object);
}
}
/**
* Returns the number of occurrences of <i>obj</i> in <i>coll</i>.
*

View File

@ -32,6 +32,8 @@ import org.apache.commons.collections.collection.PredicatedCollection;
import org.apache.commons.collections.collection.SynchronizedCollection;
import org.apache.commons.collections.collection.TransformedCollection;
import org.apache.commons.collections.collection.UnmodifiableCollection;
import org.apache.commons.collections.functors.DefaultEquator;
import org.apache.commons.collections.functors.Equator;
import org.junit.Before;
import org.junit.Test;
@ -515,6 +517,36 @@ public class CollectionUtilsTest extends MockTestCase {
assertTrue(CollectionUtils.isEqualCollection(b, a));
}
@Test
public void testIsEqualCollectionEquator() {
Collection<Integer> collB = CollectionUtils.collect(collectionB, TRANSFORM_TO_INTEGER);
// odd / even equator
final Equator<Integer> e = new Equator<Integer>() {
public boolean equate(Integer o1, Integer o2) {
if (o1.intValue() % 2 == 0 ^ o2.intValue() % 2 == 0) return false;
else return true;
}
public int hash(Integer o) {
return o.intValue() % 2 == 0 ? Integer.valueOf(0).hashCode() : Integer.valueOf(1).hashCode();
}
};
assertTrue(CollectionUtils.isEqualCollection(collectionA, collectionA, e));
assertTrue(CollectionUtils.isEqualCollection(collectionA, collB, e));
assertTrue(CollectionUtils.isEqualCollection(collB, collectionA, e));
final Equator<Number> defaultEquator = new DefaultEquator<Number>();
assertFalse(CollectionUtils.isEqualCollection(collectionA, collectionB, defaultEquator));
assertFalse(CollectionUtils.isEqualCollection(collectionA, collB, defaultEquator));
}
@Test(expected=IllegalArgumentException.class)
public void testIsEqualCollectionNullEquator() {
CollectionUtils.isEqualCollection(collectionA, collectionA, null);
}
@Test
public void testIsProperSubCollection() {
final Collection<String> a = new ArrayList<String>();