import java.util.*;
class Dog {
public Dog(String n) { name = n; }
public String name;
public boolean equals(Object o) {
System.out.println("equals called..");
if((o instanceof Dog) &&
(((Dog)o).name == name)) {
return true;
} else {
return false;
}
}
public int hashCode() {
System.out.println("hashCodecalled..");
return name.length();
}
}
class SampleClass {
public static void main(String[] args) {
Map<Object, String> m = new HashMap<Object, String>();
Dog d1 = new Dog("clover");
m.put(d1, "Dog key");
d1.name ="arthur";
System.out.println(m.get(d1));
}
}
In the above code, the output i get is:
hashCodecalled..
hashCodecalled..
Dog key
after i do d1.name ="arthur"
i was expecting output to be
hashCodecalled..``
hashCodecalled..
equals called..
null
HashMap uses equals() to compare the key to whether they are equal or not. If the equals() method return true, they are equal otherwise not equal. A single bucket can have more than one node, it depends on the hashCode() method. The better your hashCode() method is, the better your buckets will be utilized.
A HashMap is not allowed to have multiple equal keys! Not after we have overridden the equals() method on Person Class. That is the reason why we must override hashCode() method after we have overridden equals method.
You must override hashCode in every class that overrides equals. Failure to do so will result in a violation of the general contract for Object. hashCode, which will prevent your class from functioning properly in conjunction with all hash-based collections, including HashMap, HashSet, and Hashtable.
We know that two objects are considered equal only if their references point to the same object, and unless we override equals and hashCode methods, the class object will not behave properly on hash-based collections like HashMap , HashSet , and Hashtable .
Since the HashMap
has the exact object that you're looking for, it doesn't need to call equals
to verify that the object is the right one.
When you get
an object from a HashMap
, first the hashCode
is evaluated to find the right bucket. Then, the bucket is searched. But each key in the bucket is compared first using ==
. If the object is not the one that is being sought, then equals
is used.
In Java 7, the key part of the code, in the get
method of HashMap
is
if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
return e.value;
This question has been asked before in here.
According to the hashCode method, it states "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." In general, whenever you create your equals method, make sure it is consistent to the returning hashcode value.
The HashMap will always compare the objects using the hashCode before the equal method. For your case if you would like to see the equal method to be invoked, you can simulate the hash collision scenario by just making the hashcode value to be a constant. (Caveat: This is not a bad example as it impacts a lot in term of performance.)
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Map<Object, String> m = new HashMap<Object, String>();
Dog d1 = new Dog("clover");
Dog d2 = new Dog("clover 2");
m.put(d1, "Dog 1");
m.put(d2, "Dog 2");
System.out.println(m.get(d1));
}
class Dog {
private String name;
public Dog(String n) {
name = n;
}
@Override
public boolean equals(final Object o) {
System.out.println("equals called..");
return true;
}
@Override
public int hashCode() {
System.out.println("hashCodecalled..");
return 1; // constant
}}
and the result:
hashCodecalled..
hashCodecalled..
equals called..
hashCodecalled..
Dog 2
And finally of course you need to insert at least two object to make it works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With