Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HashMap adding object with equals true and same hashcode

I am trying to create custom objects for HashMap and have written code for hashcode and equals method. While adding objects in HashMap, equals method is true and hashcode is returning same value for both objects yet HashMap is adding both objects as different objects. How can this be possible? Below is my code:

class B {
    String name;
    int id;

    public B(String name, int id)
    {
        this.name=name;
        this.id=id;
    }

    public boolean equals(B b){
        if(this==b)
            return true;
        if(b==null)
            return false;
        if(this.name.equals(b.name) && this.id==b.id)
            return true;
        else
            return false;
    }

    public int hashcode(){
        return this.id;
    }

    public String toString(){
        return "name: "+name+" id: "+id;
    }
}

For testing above code, I have added following in my main class:

HashMap<B,String> sample=new HashMap<>();
B b1 = new B("Volga",1);
B b2 = new B("Volga",1);
System.out.println(b1.equals(b2));
System.out.println(b1.hashcode()+"    "+b2.hashcode());
sample.put(b1, "wrog");
sample.put(b2,"wrog");
System.out.println(sample);

This is producing following output:

true
1    1
{name: Volga id: 1=wrog, name: Volga id: 1=wrog}

Can someone please explain why is this happening?

like image 390
volga dr Avatar asked Dec 23 '22 04:12

volga dr


1 Answers

You've got two issues here:

  1. Instead of implementing equals(B) you should have implemented equals(Object) (Javadoc)
  2. It needs to be hashCode() instead of hashcode() (Javadoc)

A working implementation might look like this:

class B {
    String name;
    int id;

    public B(String name, int id) {
        this.name = name;
        this.id = id;
    }

    @Override
    public int hashCode() {
        return this.id;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        B other = (B) obj;
        if (id != other.id) {
            return false;
        }
        if (name == null) {
            if (other.name != null) {
                return false;
            }
        } else if (!name.equals(other.name)) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "name: " + name + " id: " + id;
    }
}

As a general advise, make sure to specify the @Override annotation. Your IDE and the Java compiler (javac) can then help you spot these kind of issues.

like image 152
thokuest Avatar answered Jan 13 '23 14:01

thokuest