0

I have the below class which only equals is overridden,

class S {

    String txt = null;

    S(String i) {
        txt = i;
    }       

    public boolean equals(Object o) {
        S cc = (S) o;
        if (this.txt.equals(cc.txt)) {
            return true;
        } else {
            return false;
        }
    }

    //Default hash code will be called
    /*public int hashCode(){
        return txt.hashCode();
    }*/

}

I add this class objects to a hash map as below,

    public static void main(String args[]) {
            S s1 = new S("a");
            S s2 = new S("b");
            S s3 = new S("a");

            Map m = new HashMap();
            m.put(s1, "v11");
            m.put(s2, "v22");
            m.put(s3, "v33");

            System.out.println(m.size());
            System.out.println(m.get(s1));
    }

Can explain the result 3 and v11 is printed? Shouldnt the value v11 of s1 is replace by v33 because same equals key is put as s3?

Harshana
  • 7,297
  • 25
  • 99
  • 173
  • `#equals` will only be called if two objects have the same hash code (= they would be in the same "bucket"). Have you tried to read something about the behaviour of a `HashMap`? For example this: [Understanding the workings of equals and hashCode in a HashMap](http://stackoverflow.com/q/1894377) – Tom May 14 '15 at 10:00

2 Answers2

4

You must override hashCode as well. if a.equals(b), a.hashCode() must be equal to b.hashCode(). The implementation of hashCode determines in which bucket the entry will be stored. If you don't override hashCode, you might have two equal keys stored in two different buckets.

Add this to your S class :

@Override
public int hashCode() {
    if (txt == null)
        return 0;
    return txt.hashCode();
}
Eran
  • 387,369
  • 54
  • 702
  • 768
1

The situation you decribe is a violation of the contract. If you override equals() in such a way as to break the contract of hashCode(), you must override hashCode() as well.

user207421
  • 305,947
  • 44
  • 307
  • 483