equals common interview questions
Before we start talking, let's look at some common interview questions to see if you can answer them all.
- 1. What's the difference between equals and = =?
- 2. Must two objects with equal hashcode be equal? Are equals equal?
- 3. Two objects are equal by equals. Are their hashcode s equal?
If we do not override equals and hashcode, it uses the implementation of the Object method. Let's take a brief look first
public boolean equals(Object obj) { return (this == obj); }
public static int hashCode(Object o) { return o != null ? o.hashCode() : 0; }
Why override equals
As can be seen from the above code, when comparing the equals provided by Object, it is not the value comparison, but the memory address comparison. It can be seen that to compare objects with equals, equals must be overridden.
What is the problem with rewriting equals without rewriting hashCode
Let's look at the following passage first
hashCode must be overridden in every class that overrides the equals method. If you do not do so, you will violate the general convention of hashCode, that is, what is said in the above note. As a result, this class cannot be combined, so it works normally with the hash set, which refers to HashMap, HashSet, HashTable and ConcurrentHashMap.
From the third edition of Effective Java
Conclusion: if you override equals without overriding hashCode, it and hash set will not work properly.
In that case, let's take our most familiar HashMap for demonstration and derivation. We know that the keys in HashMap cannot be repeated. If they are added repeatedly, the added keys will overwrite the previous contents. Let's see how HashMap determines the uniqueness of keys.
static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
Looking at the code, it is found that it determines the storage location in the linked list by calculating the hashCode value of the Map key. In this way, it can be inferred that if we override equals but not hashCode, there may be a contradiction of element duplication.
Let's demonstrate
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); }*/ }
public static void main(String[] args) { Employee employee1 = new Employee("Ice peak", 20); Employee employee2 = new Employee("Ice peak", 22); Employee employee3 = new Employee("Ice peak", 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)); }
Presumably, there are only two elements in the map, employee2 and employee3.
results of enforcement
The reason for this problem is that the hashCode is not rewritten, so that when the map calculates the hash value of the key, objects with the same absolute value are calculated except for inconsistent hash values.
Next, open the comment code of hashCode to see the execution result
summary
If equals is rewritten, hashCode must be rewritten. If it is not rewritten, it will cause conflicts with hash sets (HashMap, HashSet, HashTable, ConcurrentHashMap).