关于equals、hashcode和集合类的小结
一.首先明确一点:equals()方法和hashcode()方法是Object类里的方法。
查看源码可以知道,在Object类中equals(obj)方法直接返回的是 this == obj 的值。对于引用变量来说,这个式子判断的是变量中存储的内存地址是否一致。而hashcode()方法的出现,目的是为了提高哈希表的性能,也就是说,提供这样一个方法是为了提高依据hashcode进行存取的数据结构的性能的。
两者的关系:
在Object类的注释中可以看到两个原则:
两个类如果通过equals()方法比较返回的值为true,则这两个类调用hashcode()方法返回的整数值必须相等。
两个类如果通过equals()方法比较返回的值为false,则这两个类调用hashcode()方法返回的整数值建议不同(hashcode的初衷),可以相等。
故在Object类中:
equals()方法比较的方式是比较两个引用的内存地址,对于任何新 new 出来的对象来说,他们的内存地址都是不一样的。而Object类默认的hashcode计算方式和类的内存地址相关,所以他们的hashcode是不同的。
package com.njsteel.test;
public class Test {
public static void main(String[] args){
Object obj1 = new Object();
Object obj2 = new Object();
Object obj3 = obj1;
obj1.hashCode();//
obj2.hashCode();//
obj3.hashCode();//
obj1.equals(obj2);//false
obj1.equals(obj3);//true
}
}
故,我们自定义的所有类,如果没有重写equals()方法和hashcode()方法,则都是满足上述的情况的。因为自定义的类都是Object类的子类。
二. 其次,Java提供的很多便捷类都会重写equals()和hashcode()方法。
这里只说明一下String类的情况。
为什么String类要重写equals()和hashcode()方法?
一般来说,当我们想判断两个String类对象的内容是否相同时,我们就会调用equals()方法,这是API文档告诉我们的。我们比较时,一般是两个不同对象的引用。这时候,即使String对象的内容相同,如果按照Object类里equals()的判断方法判断,返回的值始终都是false。
所以为了满足这样的需要,String类equals()方法重写添加了根据内容判断两个String对象内容是否相同的逻辑代码。
equals()被重写后,hashcode()自然也要被重写,因为重写的equals()方法破坏了Object类中规定的两者的关系。于是String类里的hashcode()方法也重写成了和String内容相关的样子。以满足原来的关系。
其他的类就可以按照这样的情况以此类推。。
三. 和某些集合类的关系
先说Set:
在看书的时候,对于Set的描述有:Set集合不允许包含相同的元素。
在Set里,相同的元素是指通过equals()方法返回值为true的两个对象。在调用Set的add()方法时,就会进行这个判断(add进来的元素会与Set集合里已经有的所有元素进行equals判断,如果有相同,则add()方法返回false,添加失败)。
对于HashSet类:
HashSet是Set接口的一个实现,自然也是不允许包含相同的元素。不过判断的方法和原始的Set有点不同。
往HashSet集合里添加元素时,它不仅会通过equals()方法判断,还要调用hashcode()方法判断。只有当两个元素equals相等,并且hashcode也相等时,两个元素才是相同的元素。当其中有一个方法比较显示两个元素不一样时,HashSet会将其添加。
对于HashMap类:
我们知道HashMap的Key值是不能重复的。其实HashMap的Key值是保存在一个Set()集合里的。所以,作为Key,至少他们的hashcode是不相同的。如果两个对象是相同的Key(equals相等,hashcode也相同),值会覆盖。
验证代码:
package com.njsteel.test; import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set; public class HashSetTest {
public static void main(String[] args){
Set<MyString> set_1 = new HashSet<MyString>();
MyString myString1 = new MyString();
MyString myString2 = new MyString();
//添加一个元素
set_1.add(myString1);
//添加一个equals返回true,但是hashcode不同的元素
System.out.println(myString1.equals(myString2)+"!!!"+myString1.hashCode()+"/"+myString2.hashCode());
System.out.println(set_1.add(myString2));//true,添加成功。 //添加一个元素
Set<MyTestObject> set_2 = new HashSet<MyTestObject>();
set_2.add(new MyTestObject());
//添加一个equals返回false,但是hashcode相同的元素。
System.out.println(set_2.add(new MyTestObject())+""+set_2.size()); Map<MyString,String> map = new HashMap<MyString,String>(); map.put(myString1, "1");
map.put(myString2, "2");
for(Object key : map.keySet()){
System.out.println(map.get(key));
} }
} class MyString{ @Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
return true;
} @Override
public int hashCode() {
// TODO Auto-generated method stub
return super.hashCode();
} } class MyTestObject{ @Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
return false;
} @Override
public int hashCode() {
// TODO Auto-generated method stub
return 1;
} }
欢迎讨论指正。。
关于equals、hashcode和集合类的小结的更多相关文章
- equals(),hashcode(),克隆学习心得
equals(),hashcode(),克隆学习心得 其实在开发时候,很少去重写equals(),hashCode()方法,但是有些时候业务需要还是要重写. 注意: 重写equals()方法一定要重写 ...
- 讲的很详细的一篇关于object equals() & hashCode() 的文章
转: 讲的很详细的一篇关于object equals() & hashCode() 的文章 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java ...
- java中的 equals + hashCode
[0]README 0.1)本文转自 core java volume 1, 旨在理清 equals + hashCode方法: [1]equals方法 1.1) Object中的 equals 方法 ...
- JavaSE的包装类,自动装箱和自动拆箱 ,字符窜转换,toString(),equals(), hashCode()的区别
一.基本数据类型和包装类 包装类均位于Java.lang包,包装类和基本数据类型的对应关系如下表所示: Primitive-Type Wrapper-Class byte ...
- 在@Data注释lombok上使用继承警告等于/ hashCode(Warning equals/hashCode on @Data annotation lombok with inheritance)
生成equals / hashCode实现但没有调用超类,即使这个类没有扩展java.lang.Object.如果这是故意的,请将 @EqualsAndHashCode(callSuper = fal ...
- == equals hashCode 总结比较
在Java中: ==是运算符,用于比较两个变量是否相等. equals,是Objec类的方法,用于比较两个对象是否相等,默认Object类的equals方法是比较两个对象的地址,跟==的结果一样.Ob ...
- equals(),hashcode()方法详解
Java中的equals方法和hashCode方法是Object中的,所以每个对象都是有这两个方法的,有时候我们需要实现特定需求,可能要重写这两个方法,今天就来介绍一些这两个方法的作用. equals ...
- 借助强大的IDEA开发ide高效实现equals,hashcode以及toString方法
IDEA工具提供多种生成hashCode与equals的代码方案,注意:尽量不要使用第一个方案,第一个方案对于null不做判空处理,容易NNP问题. 对于生成toString方法方案,默认使用的是+拼 ...
- equals hashcode toString 方法的使用
package com.wu.toString; import java.util.Date; import java.util.GregorianCalendar; /** * * @author ...
随机推荐
- The connection to adb is down, and a severe error has occured.(转)
启动android模拟器时.有时会报The connection to adb is down, and a severe error has occured.的错误.在网友说在任务管理器上把所有ad ...
- 利用Socket远程发送文件
思想: 1.注意使用两个通道,一个普通对象通信通道,另一个纯净的文件字节流通道 2.利用通信通道发送文件请求,新建字节流通道,开始发送文件
- springmvc中的controller是单例的
今天发现spring3中的controller默认是单例的,若是某个controller中有一个私有的变量a,所有请求到同一个controller时,使用的a变量是共用的,即若是某个请求中修改了这个变 ...
- CentOs中yum安装LAMP+PHPMYADMIN
对于租用以及VPS,提供在Linux安装LAMP(Linux+Apache+mysql+PHP),对于这个组件,不做过多的解释,网上很多这方面的资料.下面只介绍一种安装方法,作为以后使用的一个简单文档 ...
- 在C#中如何使用资源的方法
总结一个在C#中如何使用资源的方法:一:使用本地文件1.将本地要加入的资源文本(视频,图片,文本或其它)加入项目,比如我们现在加入一个up.bmp的图片到项目中,且放在文件夹Resources下面,2 ...
- spring-cloud-event-sourcing-example-master 运行效果及说明
1.微服务架构下电商示例,部署成功!监控等技术细节未深入研究. 简单介绍: 配置服务(config-service ),端口8888,健康检查 xx:8888/hea ...
- Kernel Time和User Time分别指什么
比如你的一个程序读取并分析一个文件,读取时会调用系统接口,系统会调用驱动来从物理设备上读取数据这个就是kernel time,除此以外在你自己进程上下文中执行代码占用的时间就是user time了. ...
- 数据库为什么要用B+树结构--MySQL索引结构的实现
原理: http://blog.csdn.net/cangchen/article/details/44818485 http://blog.csdn.net/kennyrose/article/de ...
- mysql 5.6 online ddl
innodb存储引擎实现online ddl的原理是在执行创建或删除操作的同时,将DML操作日志写入到一个缓存中,待完成索引创建后再重做应用到表上,以此达到数据的一致性,这个缓存大小由参数innodb ...
- 《编写可维护的JavaScript》——JavaScript编码规范(七)
UI层的松耦合 在web开发中,用户界面(UI)是由三个彼此隔离又相互作用的层定义的. HTML用来定义页面的数据和语义. CSS用来给页面添加样式,创建视觉特征. JavaScript用来给页面添加 ...