热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java中的equals和hashCode方法

Java中的equals和hashCode方法-equals方法Object类的equals方法是比较两个对象的地址是否相等,也就是说所有类的默认equals方法都是比较地址是否相

equals 方法

Object 类的 equals 方法是比较两个对象的地址是否相等,也就是说所有类的默认 equals 方法都是比较地址是否相等;所以当需要判断复杂对象是否相等时,我们要重写 equals 方法:

//例子
@Override
public final class PhoneNumber{
    private short areaCode, prefix, lineNum;

    public boolean equals(Object o){
    if(o == this)
        return true;
    if(!(o instanceof PhoneNumber))
        return false;
    PhoneNumber pn = (PhoneNumber)o;
    return pn.lineNum == lineNum && pn.prefix == prefix &&pn.areaCode ==         areaCode;
    }
}

注意:

  • 不要将 equals 参数类型 Object 改为其他的类型,否则将重载 (Overload) Object.equals 而不是覆盖 (Override) Object.equals
  • equals 方法应该满足自反性、对称性、传递性、一致性(如果没有修改,必须保持相等)和非空性(任何对象不能等于 null,instanceof 关键字可以检查)。

hashCode 方法

哈希码有一个通用约定:

  • 一个对象多次调用 hashCode 方法都应该返回相同的值;
  • 两个对象通过 equals 方法比较返回 true,则它们的 hashCode 一定相等,也就是说相等的对象必须具有相等的散列码 (hash code);
  • 两个对象的 hashCode 相等,那么两个对象不一定相等;
  • 一个好的散列函数(hashCode)通常倾向于为不相等的对象产生不相等的散列码,这样可以提高哈希表的性能;

在判断两个对象是否相等时,会先判断 hashCode 是否相等,如果 hashCode 不相等则认为两个对象不相等;如果 hashCode 相等再进行 equals 方法比较;这是因为 hashCode 方法比 equals 方法效率高,当我们要判断 Set 集合是否存在某一个对象时,先定位到 hashCode 对应的哈希桶里寻找,如果没有对象则说明不存在该对象,如果有对象再用 equals 方法判断,大大提高了查找效率;(HashSet 底层是用 HashMap 实现的)

为什么重写 equals 方法时必须重写 hashCode 方法?

Object 类的 equals 方法比较两个对象的地址是否相等,hashCode 方法是一个本地方法,返回一个由对象的地址转换得到的值,所以如果我们重写了 equals 方法,但没有重写 hashCode 方法,这样的话当两个对象通过 equals 比较的结果是相等的,但是因为它们的 hashCode 不同,所以 Java 判断它们是不相等的两个对象,也就可以同时放到 HashSet 中,这就导致了错误的发生;

hashCode 怎么重写?

  1. 声明一个 int 类型变量 result,初始化为对象中第一个关键域的散列码(关键域指影响 equals 比较的域),按步骤 2.a 中的计算方法;
  2. 对剩下的每一个关键域 f 完成以下步骤:

    a. 计算该域 int 类型的散列码 c:

    • 该域是基本类型,散列码为 Type.hashCode(f),Type 为对应的装箱类型;
    • 该域是对象引用,如果为 null,返回 0,否则调用这个对象的 hashCode 方法;
    • 该域是数组类型,对数组的每个重要的元素计算一个散列码然后用 2.b 中的方法组合起来。如果数组中所有元素都重要,可以使用 Arrays.hashCode() 方法。

b. 按照公式将 2.a 中得到的散列码合并到 result 中:

result = 31 * result + c;

例子:

@Override
public int hashCode(){
    int result = Short.hashCode(areaCode);
    result = 31 * result + Short.hashCode(prefix);
    result = 31 * result + Short.hashCode(lineNum);
    return result;
}

参考资料:

  1. hashCode 原理分析
  2. hashCode 源码
  3. 「Effective Java 第三版」
  4. 面试官:为什么重写equals时必须重写hashCode方法?
  5. Java equals方法详解

推荐阅读
author-avatar
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有