-3

Object-1:

Employee employee1 = new Employee("AB12","Dhruv", 24);

Object-2:

Employee employee2 = new Employee("AB12", "Dhruv", 24);

output

HASH CODE FOR EMPLOYEE 1 :  43704527 
HASH CODE FOR EMPLOYEE 2 : 158893348
Muzzamil
  • 2,823
  • 2
  • 11
  • 23
kalyani
  • 23
  • 4
  • 2
    Probably because your Employee class does not override the `hashCode` method, so it inherits that method from java.lang.Object, which usually bases it on an internal memory address. – VGR Jan 08 '20 at 20:05

3 Answers3

2

Look at the following points from https://docs.oracle.com/javase/9/docs/api/java/lang/Object.html#hashCode--

  1. Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
  2. If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
  3. It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
  4. As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (The hashCode may or may not be implemented as some function of an object's memory address at some point in time.)

Now, look at the following code and its output:

class MyEmployee {
    String code;
    String name;
    int age;

    public MyEmployee(String code, String name, int age) {
        super();
        this.code = code;
        this.name = name;
        this.age = age;
    }
}

public class Main {
    public static void main(String[] args) {
        MyEmployee employee1 = new MyEmployee("AB12", "Dhruv", 24);
        MyEmployee employee2 = new MyEmployee("AB12", "Dhruv", 24);
        MyEmployee employee3 = employee1;
        System.out.println(employee1.equals(employee3));
        System.out.println("employee1.hashCode(): " + employee1.hashCode());
        System.out.println("employee3.hashCode(): " + employee3.hashCode());
        System.out.println(employee1.equals(employee2));
        System.out.println("employee2.hashCode(): " + employee2.hashCode());
    }
}

Output:

true
employee1.hashCode(): 511833308
employee3.hashCode(): 511833308
false
employee2.hashCode(): 1297685781

Since employee3 is pointing to the same object as employee1, you are getting the same hashcode for them while employee2 is pointing to a different object (although it has the same content, the keyword, new will create a separate object in the memory) and therefore, you may rarely get the same hashcode for employee2 as point#4 mentioned above from the documentation states: As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects.

You must override hashCode method in a way which should return the same hashcode for two objects having the same content e.g.

class MyEmployee {
    String code;
    String name;
    int age;

    public MyEmployee(String code, String name, int age) {
        super();
        this.code = code;
        this.name = name;
        this.age = age;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((code == null) ? 0 : code.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }   
}

public class Main {
    public static void main(String[] args) {
        MyEmployee employee1 = new MyEmployee("AB12", "Dhruv", 24);
        MyEmployee employee2 = new MyEmployee("AB12", "Dhruv", 24);
        MyEmployee employee3 = employee1;
        System.out.println(employee1.equals(employee3));
        System.out.println("employee1.hashCode(): " + employee1.hashCode());
        System.out.println("employee3.hashCode(): " + employee3.hashCode());
        System.out.println(employee1.equals(employee2));
        System.out.println("employee2.hashCode(): " + employee2.hashCode());
    }
}

Output:

true
employee1.hashCode(): 128107556
employee3.hashCode(): 128107556
false
employee2.hashCode(): 128107556

The implementation of hashCode given above produces the same hashcode for employee1 and employee2 even though equals returns false (check as point#3 mentioned above from the documentation).

A wrong way of overriding of hashCode may result in even the same objects returning different hashcodes e.g.

class MyEmployee {
    String code;
    String name;
    int age;

    public MyEmployee(String code, String name, int age) {
        super();
        this.code = code;
        this.name = name;
        this.age = age;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((code == null) ? 0 : (int) (code.length() * (Math.random() * 100)));
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        MyEmployee employee1 = new MyEmployee("AB12", "Dhruv", 24);
        MyEmployee employee2 = new MyEmployee("AB12", "Dhruv", 24);
        MyEmployee employee3 = employee1;
        System.out.println(employee1.equals(employee3));
        System.out.println("employee1.hashCode(): " + employee1.hashCode());
        System.out.println("employee1.hashCode() again: " + employee1.hashCode());
        System.out.println("employee3.hashCode(): " + employee3.hashCode());
        System.out.println(employee1.equals(employee2));
        System.out.println("employee2.hashCode(): " + employee2.hashCode());
    }
}

Output:

true
employee1.hashCode(): 66066760
employee1.hashCode() again: 66069457
employee3.hashCode(): 66073797
false
employee2.hashCode(): 66074882

This is the wrong way of overriding hashCode because invoking hashCode on the same object more than once during an execution of a Java application must consistently return the same integer (check as point#1 mentioned above from the documentation).

Now, look at the following code and its output:

class MyEmployee {
    String code;
    String name;
    int age;

    public MyEmployee(String code, String name, int age) {
        super();
        this.code = code;
        this.name = name;
        this.age = age;
    }

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

public class Main {
    public static void main(String[] args) {
        MyEmployee employee1 = new MyEmployee("AB12", "Dhruv", 24);
        MyEmployee employee2 = new MyEmployee("AB12", "Dhruv", 24);
        MyEmployee employee3 = employee1;
        System.out.println(employee1.equals(employee3));
        System.out.println("employee1.hashCode(): " + employee1.hashCode());
        System.out.println("employee3.hashCode(): " + employee3.hashCode());
        System.out.println(employee1.equals(employee2));
        System.out.println("employee2.hashCode(): " + employee2.hashCode());
    }
}

Output:

true
employee1.hashCode(): 511833308
employee3.hashCode(): 511833308
true
employee2.hashCode(): 1297685781

Since employee1.equals(employee2) returns true, the hashcode should also be returned same (check point#2 mentioned above from the documentation). However, the hashcode values of employee1 and employee2 are different which is not correct. This difference is because we haven't overridden the hashCode method. So, whenever you override equals, you should also override hashCode in a correct way.

Finally, given below is a correct way of implementing hashCode and equals:

class MyEmployee {
    String code;
    String name;
    int age;

    public MyEmployee(String code, String name, int age) {
        super();
        this.code = code;
        this.name = name;
        this.age = age;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((code == null) ? 0 : code.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

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

public class Main {
    public static void main(String[] args) {
        MyEmployee employee1 = new MyEmployee("AB12", "Dhruv", 24);
        MyEmployee employee2 = new MyEmployee("AB12", "Dhruv", 24);
        MyEmployee employee3 = employee1;
        System.out.println(employee1.equals(employee3));
        System.out.println("employee1.hashCode(): " + employee1.hashCode());
        System.out.println("employee3.hashCode(): " + employee3.hashCode());
        System.out.println(employee1.equals(employee2));
        System.out.println("employee2.hashCode(): " + employee2.hashCode());
    }
}

Output:

true
employee1.hashCode(): 128107556
employee3.hashCode(): 128107556
true
employee2.hashCode(): 128107556
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
0

Unless you @Override the hashCode() method and implement your own version, your class will use the default method inherited from Object, which generates a unique hashCode per object instance.

If you want equals and/or hashCode to only care about the members of the object, you'll need to write the implementations yourself.

Jordan
  • 2,273
  • 9
  • 16
0

Because you haven't overridden hashCode to replace the default implementation. Overriding equals doesn't change hashCode (you almost always have to override both if you override equals).

The hashCode documentation says this about the default implementation in Object:

As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the Java™ programming language.)

So you'll get distinct integers (usually) for different instances, even if they're equivalent, unless you replace hashCode.

You can do it this way

 @Override
        public int hashCode() {
            return hashId;
        }
Muzzamil
  • 2,823
  • 2
  • 11
  • 23