Java基础equals和hashCode方法要重视

1 equals规范

equals是Object类提供的方法之一,因为每一个Java类都继承自Object类,所以每一个对象都具有equals这个方法。因为Object 类中定义的equals(Object) 方法是直接使用“= =”运算符比较的两个对象,所以在没有覆盖equals(Object) 方法的情况下,equals(Object) 与“= =”运算符一样,比较的是引用。

通常你会希望放宽这个限制。一般来说如果两个对象有相同的类型和相同的字段,你会认为这两个对象相等,但也会有一些你不想加入 equals() 函数中来比较的字段。这是类型设计的一部分。

一个合适的 equals()函数必须满足以下五点条件:

  1. 反身性:对于任何 x, x.equals(x) 应该返回 true。
  2. 对称性:对于任何 x 和 y, x.equals(y) 应该返回 true当且仅当 y.equals(x) 返回 true 。
  3. 传递性:对于任何x,y,还有z,如果 x.equals(y) 返回 true 并且 y.equals(z) 返回 true,那么 x.equals(z) 应该返回 true。
  4. 一致性:对于任何 x和y,在对象没有被改变的情况下,多次调用 x.equals(y) 应该总是返回 true 或者false。
  5. 对于任何非null的x,x.equals(null)应该返回false。

2 hashCode原理

hashCode()方法是从 Object 类中继承过来的,它也用来鉴定两个对象是否相等。Object类中的hashCode()方法返回对象在内存中地址转换成的一个int值,所以如果没有重写hashCode()方法,那么任何对象的hashCode()方法都是不相等的。一般在覆盖equals方法的同时也要覆盖hashCode()方法,否则,就会违反Object.hashCode的通用约定,从而导致该类无法与所有基于散列值(hash)的集合类(HashMap、HashSet 和Hashtable)结合在一起正常运行。

设计hashCode()时最重要的因素就是:无论何时,对同一个对象调用hashCode()都应该生成同样的值。如果在将一个对象用put()添加进HashMap时产生一个hashCode()值,而用get()取出时却产生了另一个hashCode()值,那么就无法重新取得该对象了。所以,如果你的hashCode()方法依赖于对象中易变的数据,用户就要当心了,因为此数据发生变化时,hashCode()就会生成一个不同的散列码,相当于产生了一个不同的键。

此外,也不应该使hashCode()依赖于具有唯一性的对象信息,尤其是使用this值,这只能产生很糟糕的hashCode(),因为这样做无法生成一个新的键,使之与put()中原始的键值对中的键相同。

下面以String类为例。String有个特点:如果程序中有多个String对象,都包含相同的字符串序列,那么这些String对象都映射到同一块内存区域。所以new String(“hello”)生成的两个实例,虽然是相互独立的,但是对它们使用hashCode()应该生成同样的结果。通过下面的程序可以看到这种情况:

public class StringHashCodeCase {
    public static void main(String[] args) {
        String[] hellos = "Java,Java".split(",");
        System.out.println(hellos[0].hashCode());
        System.out.println(hellos[1].hashCode());
    }
}

输出结果为:

2301506
2301506

对于String而言,hashCode() 明显是基于String的内容的。

因此,要想使hashCode() 实用,它必须速度快,并且必须有意义。也就是说,它必须基于对象的内容生成散列码。记得吗,散列码不必是独一无二的(应该更关注生成速度,而不是唯一性),但是通过 hashCode() 和 equals() ,必须能够完全确定对象的身份。

因为在生成桶的下标前,hashCode()还需要做进一步的处理,所以散列码的生成范围并不重要,只要是int即可。

还有另一个影响因素:好的hashCode() 应该产生分布均匀的散列码。如果散列码都集中在一块,那么HashMap或者HashSet在某些区域的负载会很重,这样就不如分布均匀的散列函数快。

3 总结

通常来说重写equals是因为在java的集合框架中,是通过equals来判断两个对象是否相等的,equals规范的默认规则不满足。因此我们重写符合我们实际要求的判断规则。而重写hashCode只是技术要求(为了提高效率)。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农洞见

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值