HashSet集合中hashCode及equals方法详解

首先我们熟知HashSet集合中元素存储的特点:

1)不允许元素重复

2)不会记录元素添加的先后顺序

3)HashSet中比较两个对象是否相同,要使用equals()方法,不能使用 ==;

4)底层依然使用哈希表(散列)算法,其本质就是数组形式,采用此算法就为提高查询的效率;

5)插入速度也比较快,但适合于少量元素插入操作;一旦所存储元素个数满足(size * loadFoctor > size),哈希表就要扩容,此时操作速度极慢,性能就会降低!

由于HashSet集合中的元素不能重复存储,那应该怎样做呢?

1)先判断两个对象的hashCode()方法返回值是否相同,即存储的位置;

2)然后再判断两个对象的equals()方法返回值是否为true,即存储实际的对象值。

接下来我们就来讲解一下采用哈希表(散列)算法实现元素不可重复存储,具体的思想:

第一:

1)Set集合中元素没有顺序,不能重复;

2)元素重复是指:存储对象的重复;

3)何为对象的重复:内存中,所在内存编号一致(相同);

4)内存编号表示:哈希码值(哈希码值一般是  类名  和  对象所在内存地址的十六进制数字表示的集合)

第二:(现实共同观念)

现实生活中只要属性相同,我们就认为这两个对象就是同一个对象,但这与计算机比较同一个对象的方法不同(计算机使用内存地址,即哈希码值);Object类中的hashCode()方法是不可能返回两个相同的哈希码值(一个哈希码值唯一的标志了一个对象),即地址的唯一性。但是这样就不能让程序的运行符合现实生活(现实逻辑:属性相同的对象被看作是同一个对象)

于是就需要重写equals()和hashCode()方法,并且基本数据类型都重写了这两个方法!

第三:

重写这两个方法有什么用呢?

主要目的:属性相同的两个对象,返回的哈希码值是相同的!

程序向HashSet集合中添加一个元素时,先调用对象的hashCode()方法计算出该对象的哈希码值;

比较:

(1)如果该对象与集合中所存储的全部对象的哈希码值不一致,则该对象就不重复,计算出该对象在哈希表中的索引位置,直接添加;

(2)如果该对象与集合中存储的某一对象哈希码值一致(重码现象),那就需要通过equals()方法判断相同哈希码值的对象是否为同一对象(判断标准:属性是否相同);

a)相同对象,新值覆盖旧值;

b)不相同,在该索引位置,以头插的形式插入链表中。

第四:有两个疑问

(1)为什么哈希码值相同了,还有可能是不同的对象?

虽然重写hashCode()方法的主要目的:属性相同的两个对象,返回的哈希码值是相同的!

但是在重写hashCode()方法时,几乎所有的写法都无法避免一个bug:有一些对象(当然是不同的对象),会返回相同的哈希码(即重码),此时就需要借助equals()方法;

在哈希码相同的情况下,再使用equals()方法判断两个对象的属相是否一样,就可以做到万无一失了

(2)为什么经过比较哈希码值,还需要借助equals()方法判断呢?

HashSet集合底层采用了哈希算法实现,多个不同的对象可能返回的哈希码值不同,但是通过计算得到的哈希表中的索引位置相同,这样就再次需要通过equals()方法来判断这两个对象的属性值是否相同,比较完再做相应的处理!

总思路:哈希码不同时,则必为不同的对象,重写hashCode()方法时,哈希码相同(可能出现重码现象),则根据euqals()方法判断是否新值覆盖旧值;两者都是以链表头插方式!在HashSet、HashMap、HashTable中都存在这一问题!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java帮帮-微信公众号-技术文章全总结

第十六天 常用API-Date&DateFormat&Calender&System&Math&基本类型包装类&正则【悟空教程】

第十六天 常用API-Date&DateFormat&Calender&System&Math&基本类型包装类&简单正则表达式【悟空教程】

972
来自专栏java技术学习之道

java集合类详解

1356
来自专栏成猿之路

Java面试题-基础篇一

1103
来自专栏向治洪

java 之容器

在Java中,我们想要保存对象可以使用很多种手段。我们之前了解过的数组就是其中之一。但是数组具有固定的尺寸,而通常来说,程序总是在运行时根据条件来创建对象,我们...

2158
来自专栏Java后端技术栈

初探Java源码之ArrayList

在我们的日常开发中,集合类是我们基本上每个人都会用经常用到的东西,用着用着,突然有一天我心生好奇,那么java集合类的这些源码是什么呢?那么我打算接下来一个...

781
来自专栏武培轩的专栏

剑指Offer-和为S的两个数字

题目描述 输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。 输出描述: 对应每...

3214
来自专栏赵俊的Java专栏

二分查找

1131
来自专栏Java技术分享圈

Java集合之map 集合使用

712
来自专栏desperate633

LintCode 判断字符串是否没有重复字符题目分析代码

用两种方法,一种借助set没有重复元素的特点,如果add不进去,就说明重复了,就直接returnfalse 第二种方法,设立一个数组,用来判断字符出现的次数,...

672
来自专栏从零开始学 Web 前端

07 - JavaSE之容器

Collection 接口的子接口分为:Set接口(包含 HashSet类) + List接口(包含LinkedList 类和 ArrayLis t类) Ma...

952

扫码关注云+社区