preface

This article is participating in the Java Theme Month – Java Debug Notes Event, see the event link for details

Let’s get right to the hashCode method and equals method

hashCode

public native int hashCode(a);
Copy the code

The hashCode method is used to get the hashCode, also known as the hashCode, of the current object, which is essentially an integer of type int. Hash code is used to determine the position of the object in common Java collections such as HashMap, Hashtable and HashSet. The corresponding hashCode of each object is different to avoid hash collisions when stored in the collection class

equals

 public boolean equals(Object obj) {
        return (this == obj);
    }
Copy the code

By default, the equals method is implemented to determine whether two objects are the same in memory. In our daily development, we use the equals method to determine whether two objects are equal, rather than the same object, so we override the equals method. In the case of Integer, the equals method compares the values of the corresponding wrapped primitive int, and Integer overrides the hashCode method to ensure that the same object returns the same hashCode

public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
}

@Override
public int hashCode(a) {
  return Integer.hashCode(value);
}

public static int hashCode(int value) {
        return value;
}
Copy the code

So why override hashCode at the same time as equals, or more precisely, why override hashCode at the same time as equals to ensure that hashCode is equal if equals equals is true

In essence, when two objects are equal, their positions in the hash table should be the same. In the hash table, the way to calculate the location of the object is to calculate the hash value by calculating the hashCode of the object through the hash algorithm. For example, in the HashMap, when setting kv, the hash value needs to be calculated to confirm the slot. The hash value is obtained using the hashCode operation

public V put(K key, V value) {
    return putVal(hash(key), key, value, false.true);
}

static final int hash(Object key) {
        int h;
        return (key == null)?0 : (h = key.hashCode()) ^ (h >>> 16);
}
Copy the code

When obtaining the corresponding value, the slot location is obtained using the hash value. If the calculated hash value is different, the data may be put in but cannot be obtained

public V get(Object key) {
    Node<K,V> e;
    return (e = getNode(hash(key), key)) == null ? null : e.value;
}
Copy the code

At the same time, avoid variable fields when calculating hashCode. When some variables are involved in the calculation of hashCode, changing the value of the variable may make it impossible to get them out

@Data
public class Data implements Serializable {
  
  private Integer id;
  
   public boolean equals(Object obj) {
        if(obj instanceof Data){
            Data obj1 = (Data) obj;
            return obj1.id == this.id;
        }
        return false;
    }

    @Override
    public int hashCode(a) {
        return id+1; }}public static void main(String[] args) {
        Data data = new Data();
        data.setId(1);
        Map<Data, Integer> map = new HashMap<>();
        map.put(data,1);
        System.out.println(map.get(data));
        data.setId(2);
        System.out.println(map.get(data));
}
Copy the code

The output is

1
null
Copy the code