为什么要重写equals()方法与hashCode()方法
在java中,所有的对象都是继承于Object类。Ojbect类中有两个方法equals、hashCode,这两个方法都是用来比较两个对象是否相等的。
在未重写equals方法我们是继承了object的equals方法,那里的 equals是比较两个对象的内存地址,显然我们new了2个对象内存地址肯定不一样
- 对于值对象,==比较的是两个对象的值
- 对于引用对象,比较的是两个对象的地址
Object 默认的equals方法同==,一般来说我们的对象都是引用对象,要重写equals方法。
public boolean equals(Object obj) {
return (this == obj);
}
public static void main(String[] args) {
Object c=new Object();
Object d=new Object();
System.out.println(c.equals(d));//false
}
这个比较下,结果是false,也就是这两个对象不一样,但是有些业务,我们需要证明一个类的下面的实例对象时相等的,这时候我们就必须重写equlas方法了。
如下代码,我们新建一个对象Student,并重写equals与hashCode方法
public class Student {
private int no;
private String name;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (no != student.no) return false;
return !(name != null ? !name.equals(student.name) : student.name != null);
}
@Override
public int hashCode() {
int result = no;
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Student a=new Student();
Student b=new Student();
System.out.println(a.equals(b));//ture
此时可以看出a、b对象相等.
hashCode方法也是可以用来比较两个对象是否相等的。但是我们很少使用,应该说是很少直接使用。hashCode方法返回的是一个int值,可以看做是一个对象的唯一编码,如果两个对象的hashCode值相同,我们应该认为这两个对象是同一个对象。
一般如果使用java中的Map对象进行存储时,他会自动调用hashCode方法来比较两个对象是否相等。
所以如果我们对equals方法进行了重写,建议一定要对hashCode方法重写,以保证相同的对象返回相同的hash值,不同的对象返回不同的hash值。
1、重写equals方法时需要重写hashCode方法,主要是针对Map、Set等集合类型的使用;
a: Map、Set等集合类型存放的对象必须是唯一的;
b: 集合类判断两个对象是否相等,是先判断equals是否相等,如果equals返回TRUE,还要再判断HashCode返回值是否ture,只有两者都返回ture,才认为该两个对象是相等的。
2、由于Object的hashCode返回的是对象的hash值,所以即使equals返回TRUE,集合也可能判定两个对象不等,所以必须重写hashCode方法,以保证当equals返回TRUE时,hashCode也返回Ture,这样才能使得集合中存放的对象唯一。
个人感觉equals重写,是站在使用的角度上考虑的:类设计者不希望通过内存地址来比较两个对象是否相等,重写这个equals方法,能够方便的使用Collection<E>操作自定义对象E(Collection中很多方法涉及E.equals()的);而hashCode的重新,是方便Map<K,V>的使用,良好的自定义hashCode,会极大的提高Map的使用效率。 为啥说equals重新时,一定要重写hashCode?感觉这么理解不知行不行:既然自定义类重写了equals方法,说明类设计者不希望通过内存地址来比较两个对象是否相等了。而Object的hashCode也是对象的内存地址,既然不希望通过地址比较对象,那么以内存地址作为hashCode也就没有实际使用意义了,索性将自定义对象的hashCode方法也重写了吧!
参考: hashCode的作用 重写equals方法为什么要重写hashCode方法
为什么要重写equals()方法与hashCode()方法的更多相关文章
- JAVA正确地自定义比较对象---如何重写equals方法和hashCode方法
在实际应用中经常会比较两个对象是否相等,比如下面的Address类,它有两个属性:String province 和 String city. public class Address { priva ...
- HashSet中存方用户自己定义数据类型数据,重写equals方法和hashCode方法
import java.util.Set; import java.util.HashSet; public class SetTest { public static void main(Strin ...
- Hibernate中为什么要重写equals方法和hashcode方法
1.*为什么要重写equals方法,首先我们来看一下equals源码: public boolean equals(Object anObject) { if (this == anObject) { ...
- 对象作为 map 的 key 时,需要重写 equals 方法和 hashCode 方法
对象作为 map 的 key 时,需要重写 hashCode 和 equals方法 如果没有重写 hashCode 方法,那么下面的代码示例会输出 null 我们首先定义一个对象:BmapPoint, ...
- Java重写equals方法和hashCode方法
package com.ddy; public class User { private Integer id; private String name; private St ...
- HashSet中的元素必须重写equals方法和hashCode方法
http://jingyan.baidu.com/article/d5a880eb8fb61d13f147cc99.html 1.为什么必须重写这两个方法. 2.什么事hashSet去重,符合什么样的 ...
- JAVA中equals方法与hashCode方法学习
首先参考文章:http://www.oschina.net/translate/working-with-hashcode-and-equals-methods-in-java 1,equals方法的 ...
- 关于Object类的equals方法和hashCode方法
关于Object类的equals的特点,对于非空引用: 1.自反性:x.equals(x) return true : 2.对称性:x.equals(y)为true,那么y.equals(x)也为tr ...
- java中equals方法和hashcode方法的区别和联系,以及为什么要重写这两个方法,不重写会怎样
一.在Object类中的定义为:public native int hashCode();是一个本地方法,返回的对象的地址值.但是,同样的思路,在String等封装类中对此方法进行了重写.方法调用得到 ...
- Java 如何重写对象的 equals 方法和 hashCode 方法
前言:Java 对象如果要比较是否相等,则需要重写 equals 方法,同时重写 hashCode 方法,而且 hashCode 方法里面使用质数 31.接下来看看各种为什么. 一.需求: 对比两个对 ...
随机推荐
- 【HTTPS】Https和SSL学习笔记(二)
此文讲述证书的相关信息,参考文章链接http://www.guokr.com/post/116169/ 一. 证书的类型 常用的几种证书如下: (1) SSL证书,用于加密HTTP (2) 代码签名证 ...
- 输出一个等边三角形的字母阵,等边三角形的两腰为字母A,往里靠依次字母大一个(详细题目文章中描述)
题目简单的描述就是输出这么一个金字塔型的字母阵(等边三角形) /* A ABA ABCBA */ /* //解法①:对称轴法 #import <stdio.h> int main() { ...
- (转).Net平台开源作业调度框架Quartz.Net
Quartz.NET介绍: Quartz.NET是一个开源的作业调度框架,是OpenSymphony 的 Quartz API的.NET移植,它用C#写成,可用于winform和asp.net应用中. ...
- 阿里云 CentOS 安装JDK
初用阿里云,使用centOS linux64操作系统 . 自己上传jdk文件总是安装失败,原因估计是因为我的网络不好,导致文件损坏. 解决办法,直接在linux命令行模式下,到官网下载 jdk,命令如 ...
- 最近用到的Linux常用命令总结
最近用到的Linux常用命令总结 - ls :显示当前目录文件信息 `ls -a -l` - cd :目录跳转 cd .. 上级目录 cd ~ home目录 cd - 最近目录 - cat :在屏幕上 ...
- jQuery去掉导航分割线的最后一条竖线
#top #navigation ul li { float:left; width:120px; background:url(../images/navline.jpg) no-repeat 11 ...
- sublime主题推荐
PS:之前在CSDN上写的文章,现在转到博客园~ 寒假的时候发现一个sublime主题,我觉得很赞哦~~推荐给大家~~ 下载方式 step1:ctrl+shift+p 调出command palet ...
- start-stop-daemon 命令
Usage: start-stop-daemon [<option> ...] <command> Commands: -S|–start — <argument> ...
- Visual C++ 对话框增加菜单栏
1.添加菜单资源 在resourceview视图中右击选择insert,添加一个菜单资源IDR_MENU1,同时设定好响应的菜单项,例 如: 菜单1 ...
- oracle expdp 无法导出SYS下特定TABLE
创建测试表: D:\app\product\\db_1>sqlplus "/as sysdba" SQL :: Copyright (c) , , Oracle. All r ...