为何重写equals方法必须重写hashCode方法,如何重写hashCode方法

一旦重写了equals方法,就一定要重写hashCode方法。

hashCode方法的约定:

  1. 一个对象多次调用它的hashCode方法,应当返回相同的integer(哈希值)。
  2. 两个对象如果通过equals方法判定为相等,那么就应当返回相同integer。相等对象必然导致相等hashCode。
  3. 两个地址值不相等的对象调用hashCode方法不要求返回不相等的integer,但是要求拥有两个不相等integer的对象必须是不同对象。不相等hashCode必然是不相等对象导致。

在HashMap、HashTable中,put操作是先通过对象的hashCode取模运算后找到存储位置的,如果位置不存在就直接插入,如果存在,就要判定equals方法返回值是否为true,为true说明两个对象字面量是相等的,就覆盖插入。如果为false,说明发生了hash冲突。

重写hashCode方法的目标是:不相等的对象尽可能有不同的hashCode,而且必须满足的一个通用约定是:相等的对象必须具有相同的hashCode。

如果重写了equals方法不去重写hashCode方法,就会导致一种现象:相同的对象有不相等的hashCode,在HashMap机制下就会发生混乱。

重写hashCode方法的示例:

public class HashCodeTest {

    private String dishCode;
    private boolean weighing;
    private String categoryCode;
    private boolean currentPrice;
    private boolean discountable;
    private int stopSell;
    private int soldOut;
    private boolean deal = false;
    private List dealGroupList;
 
    ...
    get、set方法
    ...
 
    @Override
    public int hashCode() {
        int result = dishCode != null ? dishCode.hashCode() : 0;
        result = 31 * result +soldOut;
        result = 31 * result +stopSell;
        result = 31 * result + (currentPrice ? 1 : 0);
        result = 31 * result + (weighing ? 1 : 0);
        result = 31 * result + (categoryCode != null ? categoryCode.hashCode() : 0);
        result = 31 * result + (dealGroupList != null ? dealGroupList.hashCode() : 0);
        return result;
    }
 }

这里面为啥用个31来计算,而且很多人都是这么写的,这是因为31是个神奇的数字,任何数n*31都可以被jvm优化为(n<<5)-n,移位和减法的操作效率比乘法的操作效率高很多!
31对虚拟机的识别非常友好,对于虚拟机来说31 = 2^5 - 1

你可能感兴趣的:(为何重写equals方法必须重写hashCode方法,如何重写hashCode方法)