According to what I have read,
to use an object as the key to a hashMap, it has to provide a correct override and implementation of the equals and hashCode method. HashMap get(Key k) method calls hashCode method on the key object and applies returned hashValue to its own static hash function to find a bucket location(backing array) where keys and values are stored in form of a nested class called Entry (Map.Entry). HashMap's internal hash Method defends against poor quality hash functions.
To test these contracts, I have written a bean class with incorrect but legal implementations of the equals and hashCode method.
The class:
public class HashVO {
private String studentName;
private int age;
private boolean isAdult;
public HashVO(String studentName, int age, boolean isAdult) {
super();
this.studentName = studentName;
this.age = age;
this.isAdult = isAdult;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public boolean isAdult() {
return isAdult;
}
public void setAdult(boolean isAdult) {
this.isAdult = isAdult;
}
@Override
public String toString() {
return studentName + " : " + age + " : " + isAdult;
}
@Override
public boolean equals(Object obj) {
return false;
}
@Override
public int hashCode() {
return 31;
}
}
In this case, the hash method of the HashMap,
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
should also return same value everytime because the hashcode always returns 31. So if objects of class HashVO are used as key of a hashMap, the get method should not work, as it should go to the same bucket to retrieve the objects and the equals method always returns false so it will not be able to able to find a match for the key object.
But when I am using this method,
public static void main(String[] args) {
HashMap<HashVO, String> voMap = new HashMap<HashVO, String>();
HashVO vo = new HashVO("Item1", 25, true);
HashVO vo1 = new HashVO("Item2", 12, false);
HashVO vo2 = new HashVO("Item3", 1, false);
voMap.put(vo, "Item");
voMap.put(vo1, "Item1");
voMap.put(vo2, "Item2");
System.out.println(voMap.get(vo));
System.out.println(voMap.get(vo1));
System.out.println(voMap.get(vo2));
}
the output is correct, and showing
Item
Item1
Item2
I want to understand why this correct output is coming even as the Equals and HashCode method implementation is incorrect.