Java中的equals与hashCode方法(判断插入容器的内容是否重复)
来源:互联网 发布:爱淘宝1元天猫购物券 编辑:程序博客网 时间:2024/04/29 03:26
最近总是能够看到关于equals与hashCode之间的关系的讨论, 虽然大概了解, 但还是缺乏一个系统的总结, 在这里就稍稍深入的介绍一下, 也作为知识的整合。
在看容器类是怎么使用equals与hashCode之前,先简单回顾下equals与hashCode的一些基础:
equals与hashCode两个方法均属于Object对象,equals根据我们的需要重写, 用来判断是否是同一个内容或同一个对象,具体是判断什么,怎么判断得看怎么重写,默认的equals是比较地址。
hashCode方法返回一个int的哈希码, 同样可以重写来自定义获取哈希码的方法。
equals判定为相同, hashCode一定相同。equals判定为不同,hashCode不一定不同。
equals与hashCode被一起提到, 经常都是会出现在容器对于插入的键值是否重复的讨论中。比如下面的set对于重复键的判断:
<span style="font-size:12px;">public class Test{ public static void main(String [] args){ List list=new ArrayList(); list.add("a"); list.add("b"); list.add("a"); Set set=new HashSet(); set.add("a"); set.add("b"); set.add("a"); System.out.println(list.size()+","+set.size()); }}</span>
输出为: 3,2
道理很简单, ArrayList可以是插重复的内容, 而Set不可以插重复的内容(String重写了equals与hashCode方法)。 那这个重复的内容, Set到底是怎么判断的呢?
对不可插入重复内容的容器而言,只用equals来判断是否是重复,是不够的。下面我们自定义了一个My对象,val相同的My对象被希望判定为相同的内容。然而实际并没有被视为是相同的。
/*** @author csdn libertine1993 */import java.util.*;class My{ public int val; My(int v){ val = v; } //新手很容易以为重写了equals方法就足以判定是否重复 @Override public boolean equals(Object my){ System.out.println("equals called");//我们在equals方法内部加入输出的语句,当equals被调用则输出equals called return this.val == ((My)my).val; }}public class See{ public static void main(String [] args){ Set set=new HashSet(); set.add(new My(0)); set.add(new My(0)); set.add(new My(0)); System.out.println(set.size());//我们期望val相同的My对象会被判定为重复的内容,然而输出为3,三个val=0的对象均成功插入了。 }}
三个val = 0的My对象均插入了HashSet,set的size()返回了3, 说明hashSet并没有按照我们期望的将它们视为相同内容, 问题就出在我们没有重写hashCode方法,那么在判断的时候,我们先调用的是Object类中默认的hashCode, 它给了每一个My对象返回了不同的哈希码,那么每个对象都获得了一个空位置,自然就不需要调用equals方法,也就不会有equals called 的输出, 而HashSet中也成功插入了3个val = 0的My对象。
如果我们重写了hashCode方法,结果就很不一样。
/*** @author csdn libertine1993 */import java.util.*;class My{ public int val; My(int v){ val = v; } @Override public boolean equals(Object my){ System.out.println("equals called");//在equals中加入了输出语句,调用会输出 equals called return this.val == ((My)my).val; } @Override public int hashCode(){ System.out.println("hashCode called");//在hashCode中加入了输出语句,调用会输出 hashCode called return val;//直接以val的值作为哈希码返回 }}public class Test{ public static void main(String [] args){ Set set=new HashSet(); set.add(new My(0)); set.add(new My(0)); set.add(new My(0)); System.out.println(set.size()); }}
输出为:
正如前面所说的, 先调用了hashCode,如果被占有再调用equals判断是否是重复,对第一个my对象而言,其hashCode返回0,此时0的位置空闲,直接插入不调用equals。对第二,三个My对象而言, 得到的hashCode均为0, 由于0处位置不为空,调用equals,判定为重复,后两个均插入失败,最终输出的size为1.
总结的结论是:对于自定义对象,在插入容器中需要做重复判断的时候,我们可能需要同时重写equals与hashCode方法,才能达到我们预期的重复判断。
- Java中的equals与hashCode方法(判断插入容器的内容是否重复)
- 判断Set里的元素是否重复、==、equals、hashCode方法研究-代码演示
- Java中的equals()与hashCode()方法详解
- Java的equals方法与hashcode
- Java自带容器类的equals和hashCode方法
- hashCode方法的作用----java判断来年各个元素是否重复的机制
- Java中的hashCode()与equals()
- java中的hashcode()与equals()
- java中的equals与hashCode
- java equals与hashCode方法
- Java equals()与hashCode()方法
- Java中的equals方法与hashCode方法解析
- Java中的equals方法与hashCode方法解析
- Java中的equals方法与hashCode方法解析
- 关于Java中的equals()方法与hashCode()方法
- 浅析java中的hashcode()方法与equals()方法
- Java中的hashCode()方法与equals(Object)方法
- JAVA类中的equals()方法和hashCode()方法的重写
- 添加第三方类库造成的linker command failed with exit code 1 (use -v to see invocation)的错误调试
- DNS 解析服务器
- Hibernate 映射基础
- How to Identify and Resolve Hibernate N+1 SELECT's Problems
- 计算机网络之概念解析
- Java中的equals与hashCode方法(判断插入容器的内容是否重复)
- uva 11732 "strcmp()" Anyone?(字典树)
- 将一个带有‘?’的数拆解成两个由4-7组成的数,求该数最小值 回溯法 数学 SRM 665 Div2 Hard LuckySum
- 在CentOS7.0上安装node.js(express.js)
- 泣血推荐 各种java 技术api地址
- 1.添加mysql的jar包 2.加载JDBC驱动
- android webView.loadData乱码解决
- c简单定时器(兼容window/linux)
- Git常用命令