scolebourne 2003/12/24 15:22:54
Modified: collections/src/java/org/apache/commons/collections
DefaultMapBag.java
collections/src/java/org/apache/commons/collections/bag
AbstractMapBag.java
collections/src/test/org/apache/commons/collections/bag
AbstractTestBag.java
Log:
Unify handling of equals and hashCode
Revision Changes Path
1.13 +16 -5
jakarta-commons/collections/src/java/org/apache/commons/collections/DefaultMapBag.java
Index: DefaultMapBag.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/DefaultMapBag.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- DefaultMapBag.java 3 Dec 2003 11:37:44 -0000 1.12
+++ DefaultMapBag.java 24 Dec 2003 23:22:54 -0000 1.13
@@ -216,9 +216,20 @@
if (object == this) {
return true;
}
- return (object != null &&
- object.getClass().equals(this.getClass()) &&
- ((DefaultMapBag) object)._map.equals(this._map));
+ if (object instanceof Bag == false) {
+ return false;
+ }
+ Bag other = (Bag) object;
+ if (other.size() != size()) {
+ return false;
+ }
+ for (Iterator it = _map.keySet().iterator(); it.hasNext();) {
+ Object element = (Object) it.next();
+ if (other.getCount(element) != getCount(element)) {
+ return false;
+ }
+ }
+ return true;
}
/**
1.7 +48 -15
jakarta-commons/collections/src/java/org/apache/commons/collections/bag/AbstractMapBag.java
Index: AbstractMapBag.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/bag/AbstractMapBag.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- AbstractMapBag.java 24 Dec 2003 23:09:26 -0000 1.6
+++ AbstractMapBag.java 24 Dec 2003 23:22:54 -0000 1.7
@@ -439,6 +439,17 @@
MutableInteger(int value) {
this.value = value;
}
+
+ public boolean equals(Object obj) {
+ if (obj instanceof MutableInteger == false) {
+ return false;
+ }
+ return ((MutableInteger) obj).value == value;
+ }
+
+ public int hashCode() {
+ return value;
+ }
}
//-----------------------------------------------------------------------
@@ -527,29 +538,51 @@
//-----------------------------------------------------------------------
/**
- * Returns true if the given object is not null, has the precise type
- * of this bag, and contains the same number of occurrences of all the
- * same elements.
- *
- * @param object the object to test for equality
- * @return true if that object equals this bag
+ * Compares this Bag to another.
+ * This Bag equals another Bag if it contains the same number of occurances of
+ * the same elements.
+ *
+ * @param obj the Bag to compare to
+ * @return true if equal
*/
public boolean equals(Object object) {
if (object == this) {
return true;
}
- return (object != null &&
- object.getClass().equals(this.getClass()) &&
- ((AbstractMapBag) object).map.equals(this.map));
+ if (object instanceof Bag == false) {
+ return false;
+ }
+ Bag other = (Bag) object;
+ if (other.size() != size()) {
+ return false;
+ }
+ for (Iterator it = map.keySet().iterator(); it.hasNext();) {
+ Object element = (Object) it.next();
+ if (other.getCount(element) != getCount(element)) {
+ return false;
+ }
+ }
+ return true;
}
/**
- * Returns the hash code of the underlying map.
- *
- * @return the hash code of the underlying map
+ * Gets a hash code for the Bag compatable with the definition of equals.
+ * The hash code is defined as the sum total of a hash code for each element.
+ * The per element hash code is defined as
+ * <code>(e==null ? 0 : e.hashCode()) ^ noOccurances)</code>.
+ * This hash code is compatable with the Set interface.
+ *
+ * @return the hash code of the Bag
*/
public int hashCode() {
- return map.hashCode();
+ int total = 0;
+ for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
+ Map.Entry entry = (Map.Entry) it.next();
+ Object element = entry.getKey();
+ MutableInteger count = (MutableInteger) entry.getValue();
+ total += (element == null ? 0 : element.hashCode()) ^ count.value;
+ }
+ return total;
}
/**
1.5 +67 -2
jakarta-commons/collections/src/test/org/apache/commons/collections/bag/AbstractTestBag.java
Index: AbstractTestBag.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/collections/src/test/org/apache/commons/collections/bag/AbstractTestBag.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- AbstractTestBag.java 24 Dec 2003 23:09:26 -0000 1.4
+++ AbstractTestBag.java 24 Dec 2003 23:22:54 -0000 1.5
@@ -400,6 +400,71 @@
}
//-----------------------------------------------------------------------
+ public void testEquals() {
+ Bag bag = makeBag();
+ Bag bag2 = makeBag();
+ assertEquals(true, bag.equals(bag2));
+ bag.add("A");
+ assertEquals(false, bag.equals(bag2));
+ bag2.add("A");
+ assertEquals(true, bag.equals(bag2));
+ bag.add("A");
+ bag.add("B");
+ bag.add("B");
+ bag.add("C");
+ bag2.add("A");
+ bag2.add("B");
+ bag2.add("B");
+ bag2.add("C");
+ assertEquals(true, bag.equals(bag2));
+ }
+
+ public void testEqualsHashBag() {
+ Bag bag = makeBag();
+ Bag bag2 = new HashBag();
+ assertEquals(true, bag.equals(bag2));
+ bag.add("A");
+ assertEquals(false, bag.equals(bag2));
+ bag2.add("A");
+ assertEquals(true, bag.equals(bag2));
+ bag.add("A");
+ bag.add("B");
+ bag.add("B");
+ bag.add("C");
+ bag2.add("A");
+ bag2.add("B");
+ bag2.add("B");
+ bag2.add("C");
+ assertEquals(true, bag.equals(bag2));
+ }
+
+ public void testHashCode() {
+ Bag bag = makeBag();
+ Bag bag2 = makeBag();
+ assertEquals(0, bag.hashCode());
+ assertEquals(0, bag2.hashCode());
+ assertEquals(bag.hashCode(), bag2.hashCode());
+ bag.add("A");
+ bag.add("A");
+ bag.add("B");
+ bag.add("B");
+ bag.add("C");
+ bag2.add("A");
+ bag2.add("A");
+ bag2.add("B");
+ bag2.add("B");
+ bag2.add("C");
+ assertEquals(bag.hashCode(), bag2.hashCode());
+
+ int total = 0;
+ total += ("A".hashCode() ^ 2);
+ total += ("B".hashCode() ^ 2);
+ total += ("C".hashCode() ^ 1);
+ assertEquals(total, bag.hashCode());
+ assertEquals(total, bag2.hashCode());
+ }
+
+ //-----------------------------------------------------------------------
public void testEmptyBagSerialization() throws IOException,
ClassNotFoundException {
Bag bag = makeBag();
if (!(bag instanceof Serializable)) return;
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]