In each class, be sure to override the HashCode method when overriding equals. If you don’t, your class violates the general convention of hashCode, which prevents it from working properly in collections like HashMap and HashSet. According to the Object specification, the following are specific conventions.

  1. When executing an application, if inequalsMethod comparisons are repeated on an object without modifying any informationhashCodeMethod, it must always return the same value. Each execution from one application to another can return inconsistent values.
  2. If two objects are based onequals(Object)Method comparisons are equal, then called on both objectshashCodeThe result must be the same integer.
  3. If two objects are based onequals(Object)Method comparisons are not equal, so it is not required to be called on every objecthashCodeHave to produce different results. However, programmers should be aware that generating different results for unequal objects can improve hash tables (hash tables).

When you can’t rewritehashCodeWhen, the second critical clause is violated: equal objects must have equal hash codes (hash code)

Create a Point class with two member variables x and y and rewrite equals

    public class Point {
        private final int x, y;
    
        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
    
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if(! (objinstanceof Point)) return false;
            Point point = (Point) obj;
            returnx == point.x && y == point.y; }}Copy the code

Test it in the main method

    public static void main(String[] args) {
          Point p1 = new Point(1.2);
          Point p2 = new Point(1.2);
          System.out.println(p1.equals(p2));// true
    
          Map<Point, String> map = new HashMap<>();
          map.put(p1, "p1");
          System.out.println(map.get(p2)); // null
    
      }
Copy the code

You might think that map.get(p2) should return the string p1, but it returns NULL. This is because the Point class does not override the hashCode method, causing two equal instances p1 and P2 to return different hash codes, violating the convention of hashCode. The PUT method puts instance P1 into a hash bucket, but because p2’s hash code is not p1’s hash code, the GET method looks up other hash buckets.

The solution is as simple as overriding the hashCode method of the Point class.

    @Override
    public int hashCode(a) {
        int result = Integer.hashCode(x);
        result = 31 * result + Integer.hashCode(y);
        return result;
    }
Copy the code

The test again

    public static void main(String[] args) {
          Point p1 = new Point(1.2);
          Point p2 = new Point(1.2);
          System.out.println(p1.equals(p2));// true
    
          Map<Point, String> map = new HashMap<>();
          map.put(p1, "p1");
          System.out.println(map.get(p2)); // p1
      }
Copy the code

This time you’ll notice that map.get(p2) returns the string p1. Because hashCode returns a simple deterministic calculation, its only input is the two important attributes x and y of the Point instance, so obviously equal Point instances have the same hashCode.

In addition, the Objects class has a static method that takes any number of Objects and returns a hash code for them. This method, called hash, allows you to write a single line of hashCode methods with the same quality as the method written above in this project.

    @Override
    public int hashCode(a) {
    	return Objects.hash(x, y);
    }
Copy the code

Matters needing attention

  • When you finish ithashCodeMethod, be sure to ask yourself if you satisfy the condition that equal instances have the same hash code.
  • hashCodeThe attributes involved in theequalsDo not try to improve performance by excluding important attributes from hash code calculations.

In short, the hashCode method must be overridden every time you override equals, otherwise the program will not work. Your hashCode method must follow the general conventions specified by the Object class, and it must do the reasonable job of assigning unequal hash codes to unequal instances.