6

I have two sets:

 Set<Attribute> set1 = new HashSet<Attribute>(5);
 Set<Attribute> set2 = new HashSet<Attribute>(5);

 //add 5 attribute objects to each of them. (not necessarily the same objects)


 assertEquals(set1,set2); //<--- returns false, even though 
                         //the added attribute objects are equal

The equals method of Attribute is overridden, according to my requirements:

public abstract class Attribute implements Serializable{

public int attribute;

public abstract boolean isNumerical();

@Override
public boolean equals(Object other){
    if(!(other instanceof Attribute)){
        return false;
    }

    Attribute otherAttribute = (Attribute)other;
    return (this.attribute == otherAttribute.attribute && 
            this.isNumerical() == otherAttribute.isNumerical());
}

}

when debugging, the equals method is not even called!

Any ideas?

Razvan
  • 9,925
  • 6
  • 38
  • 51
  • 1
    See also: [Overriding equals and hashCode in Java](http://stackoverflow.com/questions/27581) – McDowell Sep 04 '12 at 10:32
  • @McDowell: thanks! I knew that if hashCode returns different values for 2 objects then there is no chance of getting a true from the equals call. I was in a hurry! :) – Razvan Sep 04 '12 at 10:36

2 Answers2

13

You're not overriding hashCode(), which means the default implementation will be used. HashSet checks for matching hash codes first, before calling equals - that's how it manages to find potential matches so efficiently. (It's easy to "bucket" an integer.)

Basically, you need to override hashCode in a manner which is consistent with your equals method.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
0

If you check the source code of HashSet contains() method calls containsKey() which calls getEntry(). As per the below source code it is clear that a proper hashcode() implementation is needed to call equals.

/**
 * Returns the entry associated with the specified key in the
 * HashMap.  Returns null if the HashMap contains no mapping
 * for the key.
 */
final Entry<K,V> getEntry(Object key) {
    int hash = (key == null) ? 0 : hash(key.hashCode());
    for (Entry<K,V> e = table[indexFor(hash, table.length)];
         e != null;
         e = e.next) {
        Object k;
        if (e.hash == hash &&
            ((k = e.key) == key || (key != null && key.equals(k))))
            return e;
    }
    return null;
}

PS: Contains() method is used from equals of AbstractCollection

Amit Deshpande
  • 19,001
  • 4
  • 46
  • 72