Equals often meets test questions
Before we get started, let’s take a look at some common interview questions and see if you can answer them all.
- What is the difference between equals and ==?
- 2. Are two objects equal in hashcode necessarily equal? Is equals equal?
- 3, Two objects are equal to equals. Are their hashcode equal?
If we don’t override equals and HashCode, it uses an implementation of the Object method. Let’s take a quick look at it
public boolean equals(Object obj) {
return (this == obj);
}
Copy the code
public static int hashCode(Object o) {
returno ! =null ? o.hashCode() : 0;
}
Copy the code
Why override equals
Equals (Object) equals (memory) equals (memory) You know that to use equals to compare objects, you have to override equals.
What is the problem with overriding equals but not hashCode
Let’s start with the following passage
Every class that overrides equals must override hashCode. Failing to do so violates the general convention of hashCode, as stated in the comments above. As a result, this class cannot be combined and therefore works with collections of hashes, namely HashMap, HashSet, HashTable, ConcurrentHashMap.
From Effective Java version 3
Conclusion: If overriding equals does not override hashCode it does not work with hash collections.
In that case, let’s use the most familiar HashMap to demonstrate the derivation. We know that keys in a HashMap cannot be repeated, and if they are added repeatedly, the last one overwrites the previous one. So let’s look at how a HashMap can determine the uniqueness of a key.
static final int hash(Object key) {
int h;
return (key == null)?0 : (h = key.hashCode()) ^ (h >>> 16);
}
Copy the code
A look at the code shows that it calculates the hashCode value of the Map key to determine where it is stored in the linked list. So it follows that if we overwrite equals but not hashCode, then there might be a contradiction of duplicate elements.
So let’s do a demonstration
public class Employee {
private String name;
private Integer age;
public Employee(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null|| getClass() ! = o.getClass())return false;
Employee employee = (Employee) o;
return Objects.equals(name, employee.name) &&
Objects.equals(age, employee.age);
}
/*@Override public int hashCode() { return Objects.hash(name, age); } * /
}
Copy the code
public static void main(String[] args) {
Employee employee1 = new Employee("Ice".20);
Employee employee2 = new Employee("Ice".22);
Employee employee3 = new Employee("Ice".20);
HashMap<Employee, Object> map = new HashMap<>();
map.put(employee1, "1");
map.put(employee2, "1");
map.put(employee3, "1");
System.out.println("equals:" + employee1.equals(employee3));
System.out.println("hashCode:" + (employee1.hashCode() == employee3.hashCode()));
System.out.println(JSONObject.toJSONString(map));
}
Copy the code
Normally, there are only two elements in the map, employee2 and Employee3.
The execution result
The reason for this problem is that hashCode is not overwritten, causing the map to compute the hash value of the key, and the object with the same absolute value to compute the inconsistent hash value.
Next, let’s open the comment code for hashCode and see the result
conclusion
If you override equals, you must override hashCode, otherwise it will cause a conflict with the HashSet (HashMap, HashSet, HashTable, ConcurrentHashMap).