hashCode,equals与==

引入

前几天软件构造课上讲了equals,课上提到如果重写了equals方法,那么也建议重写hashCode方法。我感觉这里我似懂非懂,于是CSDN查了一下,整理一下自己的理解。

== vs equals

==

在Java中**==**均是用来表示判断,如果是基本数据类型,相等返回true,不等返回false。如果是引用数据类型,那么便判断引用地址是否相同,相同返回true,不等返回false。用C语言的话来理解,是判断两个指针是否相同。

equals

equals与==不同,总的来说,equals判断是否相等,==判断是否相同

==判断是否相同。就是判断两个变量,是不是引用的同一个对象。两个对象内部成员完全一样,但在不同的地址空间,都不算作相同。

equals判断两个对象是不是相等的(不要求地址相等),那怎样算作相等呢?由我们自己决定,以重写的方法来自定义这个相等。为什么说重写呢?因为所有的类都是Object的子类,Object类中定义了equals(object o)方法。通常是选择重写这一方法,即在自定义的类中同样定义equals(object o)方法。

equals的重写

为什么选择重写

为什么选择重写Object的equals(object o)方法,而不将其中的参数类型换为自定义的类型(比如自定义的类Person)?

为了叙述方便,不妨设自定义的类为Person。分析的代码语句为arg1.equals(arg2)

因为重写的话,arg1.equals(arg2),arg2的类型可以为任意类型。

arg1的reference type可以是Person,也可以是Person的父类(所有的类都继承自Object,均有equals,所以父类没有重写equals也能过编译),只要其object type是Person,那么调用的equals()便是重写的Person类中的equals。

而如果equals的参数类型为Person的话,便是重载。这么写就要注意:

  1. 如果arg1的reference type是Person的父类,那么就会调用其父类的equals,父类没有重写equals的则调用的是Object类的equals。而Object类中的equals(Object o)是通过地址是否相同来作为相等的标准。
  2. 如果arg2的reference type不是Person,也不是Person的子类,那么编译解析的时候,就同样匹配不到Person类里重载的equals(Person p)。重载的情况下,运行时调用哪个方法,编译解析时便确定下来了。

所以的话,通常是重写Object类中的equals(Object o)方法。

怎么重写

重写的话,函数的返回类型,函数名,参数列表全部不能改变。
在这里插入图片描述
以IDEA提供的模板为例。可以借鉴一下。

hashCode与equal

背景

如果我们在一个Collection里要找一个对象,一般使用contains(Object o)。以下是它的规约。
在这里插入图片描述
重点在于这一句话:

returns true if and only if this collection contains at least one element e such that (o==null ? e==null : o.equals(e))

简而言之,只要符合你给定的相等条件即可。

关于寻找的方法,并不是遍历,而是Hash的方法。

比如对于这个代码片段:

Person p=new Person("CYF","1191000606","计算学部");
personList.contains(p);

每一个Person对象放入personList里面时,都会根据对象内部的字段值,计算一个int值,称其为hashcode,然后将这个int值和对象的地址以键值对的方式放入Hash Tables里面。但是会有不同的对象计算出了相同的hashcode,于是Hash Tables就不是一个hashcode对一个地址,而是一个hashcode对应一组地址。

hashcode在Hash Tables里的摆放,也使用hash的方法,即hashcode在Hash Tables里面的索引,由hashcode的值来决定。

当要在里面寻找p时,就根据p的三个属性"CYF",“1191000606”,"计算学部"计算hashcode,在Hash Tables里面找,找到这一个hashcode对应了三个对象的地址,于是取这三个对象与p调用equals()一一比较。

重写equals,必须重写hashCode

比如同样是上面的例子,由于转专业情况的存在,我们判断相等不再依靠院系,只要名字,学号相等就看做相等,于是我们重写了equals方法。但是我们没有重写hashCode方法,对象hashcode的计算还是依靠姓名,学号,院系三个属性的值。

此时personList里面有一个对象q,其三个字段的值为"CYF",“1191000606”,“经济与管理学院”。由于p,q的hashcode不同,并没有找到q。这样就导致了不好的事情。

以上过程全部发生在contains的调用中,我们只要负责提供hashCode,equals方法。

可以这么看,寻找与给定对象equals的过程中,我们先使用hashCode的方法缩小遍历范围,缩小到hashCode相等的范围内。上述错误的原因在于,我们要找的equals的对象,他们的hashCode不同。

所以如果重写了equals方法,改变了判断相等的标准,那么hashCode也必须重写。重写的要求是如果equal,计算出的hashcode必须相等。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值