美文网首页Effective Java Sencond Edition
Effective Java 第9条: 覆盖 equals 时总

Effective Java 第9条: 覆盖 equals 时总

作者: linyk3 | 来源:发表于2019-01-03 11:33 被阅读0次

在每个覆盖了equals 方法的类中,也必须覆盖 hashCode 方法.
否则违反Object.hashCode 通用规定,从而导致无法结合所有基于散列的集合一起正常运作.

Object.hashCode 约定的内容:

  • 在应用程序执行期间,只要对象的equals方法的比较操作所用到的信息没有被修改,那么多次调用hashCode方法都必须始终如一的返回同一个整数. 同一个程序被多次执行过程中, hashCode返回的整数可以不一致.
  • 如果 x.equals(y) == true 那么要求 x.hashCode() == y.hashCode()
  • 如果 x.equals(y) == false, 没有要求 x.hashCode != y.hashCode, 但是不同对象产生不同的hashCode有利于hash tables 的性能.

一个好的散列函数通常倾向于:为不相等的对象产生不相等的散列码.
简单的hash方法:

    1. int result = 17 (要求非0的整数即可)
    1. 对于对象中的每个关键域f(也就是 equals 中涉及的每个域),
      • 2.1 计算该域的散列码 c:
        - i. boolean 类型: c = (f ? 1:0)
        - ii. byte,char,shot,int类型, c = int(f)
        - iii. longs类型: c = (int)(f ^ (f >> 32))
        - iv. float类型: c = Float.floatToIntBits(f)
        - v. double类型: fb = Double.doubleToLongBits(f), c = (int)(fb ^ ( fb >> 32))
        - vi. 对象引用类型: c = (f = null ? 0: f.hashCode())
        - vii. 数组类型: c = Arrays.hashCode()
        • 2.2 rerult = 31 * result + c (使用奇素数31,防止乘法溢出, 并且 31 * i = (i << 5) - i)
    1. return result
    1. 检查是否满足相等的实例具有相等的散列码.

缓存hashCode,并延迟初始化:

private volatile int hashCode;
// equals 方法比较涉及的三个域: short areaCode, short prefix, short lineNumber
@Override 
public int hashCode() {
    int result = hashCode;
    if (result == null) {
        result = 17;
        result = 31 * result * areaCode;
        result = 31 * result * prefix;
        result = 31 * result * lineNumber;
        hashCode = result;
    }
    return result;
}

**不要试图从散列码计算中排除一个对象的关键部分来提高性能.这样虽然计算hashCode可能会快一点,但是hash表不一定好.

相关文章

网友评论

    本文标题:Effective Java 第9条: 覆盖 equals 时总

    本文链接:https://www.haomeiwen.com/subject/kyffrqtx.html