【Effective Java】重写equals方法时必须重写hashCode 方法

必须谨记:对于每一个类,重写equals方法时,必须重写hashCode方法。如果没有遵照此规定,则在所有基于hash计算的类中(如:HashMapHashSetHashTable)都会出问题。

hashCode约定

Object规范中有这样的约定:

  • 在程序相同执行过程中多次调用同个对象,哈希值必须返回相同。但不是相同调用过程则不必相同;
  • 如果两个对象调用equals()方法相同,则hashCode()方法返回值必须相同;
  • 如果两个对象调用equals()方法不相同,并不需要两个对象的哈希值不相同。但是开发者必须意识到,不同的对象产生不同的哈希值可以提高像HashTable这样类的性能

重写hashCode方法

若需要重写hashCode方法,可以参照如下步骤:
1. 取个非0的常量值,赋值给result。譬如,result=17
2. 对类中每一个关键属性(equals方法中用到的属性)f,作如下处理
1). 计算属性f的哈希值,赋值给c

    a. `f`为`boolean`类型,`c = f ? 1 : 0`

    b. `f`为`byte`、`char`、`short`、`int`类型,`c = (int)f`

    c. `f`为`long`类型,`c = (int)(f ^ (f >>> 32))`

    d. `f`为`float`类型,`c = Float.floatToIntBits(f)`

    e. `f`为`double`类型,首先`temp = Double.doubleToLongBits(f)`,之后按照2.1).c步骤来计算`c = (int)(temp ^ (temp >>> 32))`

    f. `f`为对象引用,并且`equals`方法是通过迭代`f`的属性进行判断的,则`hashCode`方法也必须迭代计算`f`中的`hashCode`值。若需要更复杂的计算,则为此属性计算个范式,然后针对这个范式调用`hashCode`。如果属性为`null`,一般返回0
    g. `f`为数组,则需将每一个元素单独按2.1).(a-f)步骤处理,然后按照2.2)将哈希值组合起来。若数组中每个元素都很重要,可以利用`Arrays.hashCode`方法计算
2). 将2.1)中计算的`c`合并到`result`中:`result = 31 * result + c`

3. 返回result

猜你喜欢

转载自blog.csdn.net/xl890727/article/details/80163581