[COLLECTIONS-543] AbstractCollectionDecorator does not forward equals and hashCode anymore to the backing collection.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/collections/trunk@1651115 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
32155107dd
commit
30e5023265
|
@ -22,6 +22,9 @@
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<release version="4.1" date="TBD" description="">
|
<release version="4.1" date="TBD" description="">
|
||||||
|
<action issue="COLLECTIONS-543" dev="tn" type="fix">
|
||||||
|
"AbstractCollectionDecorator" doesn't forward equals and hashCode anymore.
|
||||||
|
</action>
|
||||||
<action issue="COLLECTIONS-544" dev="tn" type="fix" due-to="Oswaldo Olivo">
|
<action issue="COLLECTIONS-544" dev="tn" type="fix" due-to="Oswaldo Olivo">
|
||||||
Documented runtime complexity of "CollectionUtils#retainAll(Collection, Collection).
|
Documented runtime complexity of "CollectionUtils#retainAll(Collection, Collection).
|
||||||
</action>
|
</action>
|
||||||
|
|
|
@ -63,6 +63,16 @@ public abstract class AbstractBagDecorator<E>
|
||||||
return (Bag<E>) super.decorated();
|
return (Bag<E>) super.decorated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object object) {
|
||||||
|
return object == this || decorated().equals(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return decorated().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
public int getCount(final Object object) {
|
public int getCount(final Object object) {
|
||||||
|
|
|
@ -87,6 +87,16 @@ public class PredicatedBag<E> extends PredicatedCollection<E> implements Bag<E>
|
||||||
return (Bag<E>) super.decorated();
|
return (Bag<E>) super.decorated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object object) {
|
||||||
|
return object == this || decorated().equals(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return decorated().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
public boolean add(final E object, final int count) {
|
public boolean add(final E object, final int count) {
|
||||||
|
|
|
@ -82,6 +82,23 @@ public class SynchronizedBag<E> extends SynchronizedCollection<E> implements Bag
|
||||||
return (Bag<E>) decorated();
|
return (Bag<E>) decorated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object object) {
|
||||||
|
if (object == this) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
synchronized (lock) {
|
||||||
|
return getBag().equals(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
synchronized (lock) {
|
||||||
|
return getBag().hashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
public boolean add(final E object, final int count) {
|
public boolean add(final E object, final int count) {
|
||||||
|
|
|
@ -18,10 +18,10 @@ package org.apache.commons.collections4.bag;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.collections4.set.TransformedSet;
|
|
||||||
import org.apache.commons.collections4.Bag;
|
import org.apache.commons.collections4.Bag;
|
||||||
import org.apache.commons.collections4.Transformer;
|
import org.apache.commons.collections4.Transformer;
|
||||||
import org.apache.commons.collections4.collection.TransformedCollection;
|
import org.apache.commons.collections4.collection.TransformedCollection;
|
||||||
|
import org.apache.commons.collections4.set.TransformedSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decorates another {@link Bag} to transform objects that are added.
|
* Decorates another {@link Bag} to transform objects that are added.
|
||||||
|
@ -110,6 +110,16 @@ public class TransformedBag<E> extends TransformedCollection<E> implements Bag<E
|
||||||
return (Bag<E>) decorated();
|
return (Bag<E>) decorated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object object) {
|
||||||
|
return object == this || decorated().equals(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return decorated().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
public int getCount(final Object object) {
|
public int getCount(final Object object) {
|
||||||
|
|
|
@ -342,6 +342,16 @@ public abstract class AbstractDualBidiMap<K, V> implements BidiMap<K, V> {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object object) {
|
||||||
|
return object == this || decorated().equals(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return decorated().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean removeAll(final Collection<?> coll) {
|
public boolean removeAll(final Collection<?> coll) {
|
||||||
if (parent.isEmpty() || coll.isEmpty()) {
|
if (parent.isEmpty() || coll.isEmpty()) {
|
||||||
|
|
|
@ -34,6 +34,19 @@ import java.util.Iterator;
|
||||||
* {@link #iterator()}. Instead it simply returns the value from the
|
* {@link #iterator()}. Instead it simply returns the value from the
|
||||||
* wrapped collection. This may be undesirable, for example if you are trying
|
* wrapped collection. This may be undesirable, for example if you are trying
|
||||||
* to write an unmodifiable implementation it might provide a loophole.
|
* to write an unmodifiable implementation it might provide a loophole.
|
||||||
|
* <p>
|
||||||
|
* This implementation does not forward the hashCode and equals methods through
|
||||||
|
* to the backing object, but relies on Object's implementation. This is necessary
|
||||||
|
* to preserve the symmetry of equals. Custom definitions of equality are usually
|
||||||
|
* based on an interface, such as Set or List, so that the implementation of equals
|
||||||
|
* can cast the object being tested for equality to the custom interface.
|
||||||
|
* AbstractCollectionDecorator does not implement such custom interfaces directly;
|
||||||
|
* they are implemented only in subclasses. Therefore, forwarding equals would break
|
||||||
|
* symmetry, as the forwarding object might consider itself equal to the object being
|
||||||
|
* tested, but the reverse could not be true. This behavior is consistent with the
|
||||||
|
* JDK's collection wrappers, such as {@link java.util.Collections#unmodifiableCollection(Collection)}.
|
||||||
|
* Use an interface-specific subclass of AbstractCollectionDecorator, such as
|
||||||
|
* AbstractListDecorator, to preserve equality behavior, or override equals directly.
|
||||||
*
|
*
|
||||||
* @param <E> the type of the elements in the collection
|
* @param <E> the type of the elements in the collection
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
|
@ -144,16 +157,6 @@ public abstract class AbstractCollectionDecorator<E>
|
||||||
return decorated().retainAll(coll);
|
return decorated().retainAll(coll);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(final Object object) {
|
|
||||||
return object == this || decorated().equals(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return decorated().hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return decorated().toString();
|
return decorated().toString();
|
||||||
|
|
|
@ -65,6 +65,16 @@ public abstract class AbstractListDecorator<E> extends AbstractCollectionDecorat
|
||||||
return (List<E>) super.decorated();
|
return (List<E>) super.decorated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object object) {
|
||||||
|
return object == this || decorated().equals(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return decorated().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
public void add(final int index, final E object) {
|
public void add(final int index, final E object) {
|
||||||
|
|
|
@ -94,6 +94,16 @@ public class PredicatedList<E> extends PredicatedCollection<E> implements List<E
|
||||||
return (List<E>) super.decorated();
|
return (List<E>) super.decorated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object object) {
|
||||||
|
return object == this || decorated().equals(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return decorated().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
public E get(final int index) {
|
public E get(final int index) {
|
||||||
|
|
|
@ -114,6 +114,16 @@ public class TransformedList<E> extends TransformedCollection<E> implements List
|
||||||
return (List<E>) decorated();
|
return (List<E>) decorated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object object) {
|
||||||
|
return object == this || decorated().equals(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return decorated().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
public E get(final int index) {
|
public E get(final int index) {
|
||||||
|
|
|
@ -24,6 +24,12 @@ import org.apache.commons.collections4.collection.AbstractCollectionDecorator;
|
||||||
* Decorates another {@link Queue} to provide additional behaviour.
|
* Decorates another {@link Queue} to provide additional behaviour.
|
||||||
* <p>
|
* <p>
|
||||||
* Methods are forwarded directly to the decorated queue.
|
* Methods are forwarded directly to the decorated queue.
|
||||||
|
* <p>
|
||||||
|
* This implementation does not forward the hashCode and equals methods through
|
||||||
|
* to the backing object, but relies on Object's implementation. This is
|
||||||
|
* necessary as some Queue implementations, e.g. LinkedList, have custom a
|
||||||
|
* equals implementation for which symmetry can not be preserved.
|
||||||
|
* See class javadoc of AbstractCollectionDecorator for more information.
|
||||||
*
|
*
|
||||||
* @param <E> the type of the elements in the queue
|
* @param <E> the type of the elements in the queue
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
|
|
|
@ -63,4 +63,14 @@ public abstract class AbstractSetDecorator<E> extends AbstractCollectionDecorato
|
||||||
return (Set<E>) super.decorated();
|
return (Set<E>) super.decorated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object object) {
|
||||||
|
return object == this || decorated().equals(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return decorated().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,4 +86,14 @@ public class PredicatedSet<E> extends PredicatedCollection<E> implements Set<E>
|
||||||
return (Set<E>) super.decorated();
|
return (Set<E>) super.decorated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object object) {
|
||||||
|
return object == this || decorated().equals(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return decorated().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,4 +101,14 @@ public class TransformedSet<E> extends TransformedCollection<E> implements Set<E
|
||||||
super(set, transformer);
|
super(set, transformer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object object) {
|
||||||
|
return object == this || decorated().equals(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return decorated().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import java.util.Set;
|
||||||
import org.apache.commons.collections4.AbstractObjectTest;
|
import org.apache.commons.collections4.AbstractObjectTest;
|
||||||
import org.apache.commons.collections4.Bag;
|
import org.apache.commons.collections4.Bag;
|
||||||
import org.apache.commons.collections4.BulkTest;
|
import org.apache.commons.collections4.BulkTest;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.collections4.MapIterator;
|
import org.apache.commons.collections4.MapIterator;
|
||||||
import org.apache.commons.collections4.MultiValuedMap;
|
import org.apache.commons.collections4.MultiValuedMap;
|
||||||
import org.apache.commons.collections4.bag.AbstractBagTest;
|
import org.apache.commons.collections4.bag.AbstractBagTest;
|
||||||
|
@ -754,7 +755,7 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
|
||||||
(MultiValuedMap<?, ?>) readExternalFormFromDisk(getCanonicalFullCollectionName(map));
|
(MultiValuedMap<?, ?>) readExternalFormFromDisk(getCanonicalFullCollectionName(map));
|
||||||
assertEquals("Map is the right size", map.size(), map2.size());
|
assertEquals("Map is the right size", map.size(), map2.size());
|
||||||
for (final Object key : map.keySet()) {
|
for (final Object key : map.keySet()) {
|
||||||
assertEquals("Map had inequal elements", map.get(key), map2.get(key));
|
assertTrue("Map had inequal elements", CollectionUtils.isEqualCollection(map.get(key), map2.get(key)));
|
||||||
if (isRemoveSupported()) {
|
if (isRemoveSupported()) {
|
||||||
map2.remove(key);
|
map2.remove(key);
|
||||||
}
|
}
|
||||||
|
@ -1071,10 +1072,12 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
|
||||||
return AbstractMultiValuedMapTest.this.makeObject().asMap();
|
return AbstractMultiValuedMapTest.this.makeObject().asMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Map<K, Collection<V>> makeFullMap() {
|
public Map<K, Collection<V>> makeFullMap() {
|
||||||
return AbstractMultiValuedMapTest.this.makeFullMap().asMap();
|
return AbstractMultiValuedMapTest.this.makeFullMap().asMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public K[] getSampleKeys() {
|
public K[] getSampleKeys() {
|
||||||
K[] samplekeys = AbstractMultiValuedMapTest.this.getSampleKeys();
|
K[] samplekeys = AbstractMultiValuedMapTest.this.getSampleKeys();
|
||||||
|
@ -1085,6 +1088,7 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
|
||||||
return (K[]) finalKeys;
|
return (K[]) finalKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Collection<V>[] getSampleValues() {
|
public Collection<V>[] getSampleValues() {
|
||||||
V[] sampleValues = AbstractMultiValuedMapTest.this.getSampleValues();
|
V[] sampleValues = AbstractMultiValuedMapTest.this.getSampleValues();
|
||||||
|
@ -1095,6 +1099,7 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
|
||||||
return colArr;
|
return colArr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Collection<V>[] getNewSampleValues() {
|
public Collection<V>[] getNewSampleValues() {
|
||||||
Object[] sampleValues = { "ein", "ek", "zwei", "duey", "drei", "teen" };
|
Object[] sampleValues = { "ein", "ek", "zwei", "duey", "drei", "teen" };
|
||||||
|
|
Loading…
Reference in New Issue