diff --git a/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java b/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java index e8cc9c961..8082c1685 100644 --- a/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java +++ b/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java @@ -18,9 +18,12 @@ package org.apache.commons.collections4.multimap; import java.io.Serializable; import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Map; +import java.util.Map.Entry; import org.apache.commons.collections4.ListUtils; import org.apache.commons.collections4.ListValuedMap; @@ -97,6 +100,49 @@ public abstract class AbstractListValuedMap extends AbstractMultiValuedMap return ListUtils.emptyIfNull((List) getMap().remove(key)); } + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (obj instanceof ListValuedMap == false) { + return false; + } + ListValuedMap other = (ListValuedMap) obj; + if (other.size() != size()) { + return false; + } + Iterator it = keySet().iterator(); + while (it.hasNext()) { + Object key = it.next(); + List list = get(key); + List otherList = other.get(key); + if (otherList == null) { + return false; + } + if (ListUtils.isEqualList(list, otherList) == false) { + return false; + } + } + return true; + } + + @Override + public int hashCode() { + int h = 0; + Iterator>> it = getMap().entrySet().iterator(); + while (it.hasNext()) { + Entry> entry = it.next(); + K key = entry.getKey(); + List valueList = (List) entry.getValue(); + h += (key == null ? 0 : key.hashCode()) ^ ListUtils.hashCodeForList(valueList); + } + return h; + } + /** * Wrapped list to handle add and remove on the list returned by get(object) */ @@ -173,6 +219,34 @@ public abstract class AbstractListValuedMap extends AbstractMultiValuedMap return list.subList(fromIndex, toIndex); } + @Override + public boolean equals(Object other) { + final List list = (List) getMapping(); + if (list == null) { + return Collections.emptyList().equals(other); + } + if (other == null) { + return false; + } + if (!(other instanceof List)) { + return false; + } + List otherList = (List) other; + if (ListUtils.isEqualList(list, otherList) == false) { + return false; + } + return true; + } + + @Override + public int hashCode() { + final List list = (List) getMapping(); + if (list == null) { + return Collections.emptyList().hashCode(); + } + return ListUtils.hashCodeForList(list); + } + } /** Values ListItrerator */ diff --git a/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java b/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java index 238675284..907e49fc5 100644 --- a/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java +++ b/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java @@ -396,7 +396,6 @@ public class AbstractMultiValuedMap implements MultiValuedMap, Seria return new MultiValuedMapIterator(); } - @SuppressWarnings("rawtypes") @Override public boolean equals(Object obj) { if (this == obj) { @@ -412,7 +411,7 @@ public class AbstractMultiValuedMap implements MultiValuedMap, Seria if (other.size() != size()) { return false; } - Iterator it = keySet().iterator(); + Iterator it = keySet().iterator(); while (it.hasNext()) { Object key = it.next(); Collection col = get(key); @@ -420,21 +419,34 @@ public class AbstractMultiValuedMap implements MultiValuedMap, Seria if (otherCol == null) { return false; } - if (col.size() != otherCol.size()) { + if (CollectionUtils.isEqualCollection(col, otherCol) == false) { return false; } - for (Object value : col) { - if (!otherCol.contains(value)) { - return false; - } - } } return true; } @Override public int hashCode() { - return getMap().hashCode(); + int h = 0; + Iterator>> it = getMap().entrySet().iterator(); + while (it.hasNext()) { + Entry> entry = it.next(); + K key = entry.getKey(); + Collection valueCol = entry.getValue(); + int vh = 0; + if (valueCol != null) { + Iterator colIt = valueCol.iterator(); + while (colIt.hasNext()) { + V val = colIt.next(); + if (val != null) { + vh += val.hashCode(); + } + } + } + h += (key == null ? 0 : key.hashCode()) ^ vh; + } + return h; } @Override @@ -588,7 +600,6 @@ public class AbstractMultiValuedMap implements MultiValuedMap, Seria return col.toArray(a); } - @SuppressWarnings("rawtypes") @Override public boolean equals(Object other) { final Collection col = getMapping(); @@ -601,15 +612,10 @@ public class AbstractMultiValuedMap implements MultiValuedMap, Seria if(!(other instanceof Collection)){ return false; } - Collection otherCol = (Collection) other; - if (col.size() != otherCol.size()) { + Collection otherCol = (Collection) other; + if (CollectionUtils.isEqualCollection(col, otherCol) == false) { return false; } - for (Object value : col) { - if (!otherCol.contains(value)) { - return false; - } - } return true; } @@ -619,7 +625,15 @@ public class AbstractMultiValuedMap implements MultiValuedMap, Seria if (col == null) { return CollectionUtils.EMPTY_COLLECTION.hashCode(); } - return col.hashCode(); + int h = 0; + Iterator it = col.iterator(); + while (it.hasNext()) { + V val = it.next(); + if (val != null) { + h += val.hashCode(); + } + } + return h; } @Override diff --git a/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java b/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java index 13778b727..bc9cd261a 100644 --- a/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java +++ b/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java @@ -16,8 +16,12 @@ */ package org.apache.commons.collections4.multimap; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; import java.util.Map; import java.util.Set; +import java.util.Map.Entry; import org.apache.commons.collections4.SetUtils; import org.apache.commons.collections4.SetValuedMap; @@ -93,6 +97,49 @@ public abstract class AbstractSetValuedMap extends AbstractMultiValuedMap< return SetUtils.emptyIfNull((Set) getMap().remove(key)); } + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (obj instanceof SetValuedMap == false) { + return false; + } + SetValuedMap other = (SetValuedMap) obj; + if (other.size() != size()) { + return false; + } + Iterator it = keySet().iterator(); + while (it.hasNext()) { + Object key = it.next(); + Set set = get(key); + Set otherSet = other.get(key); + if (otherSet == null) { + return false; + } + if (SetUtils.isEqualSet(set, otherSet) == false) { + return false; + } + } + return true; + } + + @Override + public int hashCode() { + int h = 0; + Iterator>> it = getMap().entrySet().iterator(); + while (it.hasNext()) { + Entry> entry = it.next(); + K key = entry.getKey(); + Set valueSet = (Set) entry.getValue(); + h += (key == null ? 0 : key.hashCode()) ^ SetUtils.hashCodeForSet(valueSet); + } + return h; + } + /** * Wrapped set to handle add and remove on the collection returned by * get(object) @@ -103,6 +150,34 @@ public abstract class AbstractSetValuedMap extends AbstractMultiValuedMap< super(key); } + @Override + public boolean equals(Object other) { + final Set set = (Set) getMapping(); + if (set == null) { + return Collections.emptySet().equals(other); + } + if (other == null) { + return false; + } + if (!(other instanceof Set)) { + return false; + } + Set otherSet = (Set) other; + if (SetUtils.isEqualSet(set, otherSet) == false) { + return false; + } + return true; + } + + @Override + public int hashCode() { + final Set set = (Set) getMapping(); + if (set == null) { + return Collections.emptySet().hashCode(); + } + return SetUtils.hashCodeForSet(set); + } + } } diff --git a/src/test/java/org/apache/commons/collections4/multimap/MultiValuedHashMapTest.java b/src/test/java/org/apache/commons/collections4/multimap/MultiValuedHashMapTest.java index 267d79d20..0d4da5b24 100644 --- a/src/test/java/org/apache/commons/collections4/multimap/MultiValuedHashMapTest.java +++ b/src/test/java/org/apache/commons/collections4/multimap/MultiValuedHashMapTest.java @@ -163,6 +163,64 @@ public class MultiValuedHashMapTest extends AbstractMultiValuedMapTest