关于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 ...
随机推荐
- 创建redis集群
假设你已经安装好了redis ,如果还没有请安装 将多个实例跑起来 创建一个目录,比如 redis-cluster 把redis-server拷贝到这个目录下 在目录下为每一个实例创建一个文件夹 在每 ...
- 基于Java Netty框架构建高性能的部标808协议的GPS服务器
使用Java语言开发一个高质量和高性能的jt808 协议的GPS通信服务器,并不是一件简单容易的事情,开发出来一段程序和能够承受数十万台车载接入是两码事,除去开发部标808协议的固有复杂性和几个月长周 ...
- Android -- OkHttp的简单使用和封装
1,昨天把okHttp仔细的看了一下,以前都是调用同事封装好了的网络框架,直接使用很容易,但自己封装却不是那么简单,还好,今天就来自我救赎一把,就和大家写写从最基础的OKHttp的简单get.post ...
- Linux系统安装-系统分区
ctrl+alt+enter全屏
- 算法第四版 用eclipse实现书中UnionFind例子
一 安装环境 直接下载algs4.exe 下载完成后C:\Users\zle 下面会有algs4 文件夹 原文: Our installer downloads, installs, and conf ...
- WCF学习目的
WCF,window communication Foundation,是微软推出的面向服务应用的一款产品. 近来为一个WEB app前端项目写后台接口.涉及到跨域访问,服务代理等方面的内容.项目的需 ...
- 修改后的CopyFile类
这是修改后的CopyFile类,前面那个类有局限性,它不能复制大文件 这是我第一次写成一个能够实际应用的类,感谢博主们的无私奉献,感谢SeayXu老师的提点 但是这个类也并不是完美无缺,它复制文件没有 ...
- MVC 中301永久重定向
public class PermanentRedirectResult : ViewResult { public string Url { get; set; } public Permanent ...
- JS 鼠标滚轮事件(mousewheel/DOMMouseScroll)
onmousewheel (FireFox不支持此事件) // IE/Opera/Chrome/Safari document.body.onmousewheel = function(event) ...
- HDU 3605:Escape(最大流+状态压缩)
http://acm.hdu.edu.cn/showproblem.php?pid=3605 题意:有n个人要去到m个星球上,这n个人每个人对m个星球有一个选择,即愿不愿意去,"Y" ...