浅谈自己对java中哈希表与HashSet的理解

哈希表:
哈希表底层使用的是数组机制。当向哈希表中存放元素时,会通过hash散列算法计算出该元素在哈希数组的存放位置,当有元素通过hash散列算法计算出的存放位置和之前某元素一样,此时便会产生哈希冲突。

常见hash散列算法有:
1.直接定址法
2.数据分析法
3.平方取中法
4.取模法
5.随机数法

这里以取模法为例,给大家简单解释一下向哈希表存放元素的过程:
现需要向哈希表中依次插入这些数据:【11,12,13,22,34】
我们先给这些数据取个模:
11 mod 10 = 1
12 mod 10 = 2
13 mod 10 = 3
22 mod 10 = 2
34 mod 10 = 4
通过取模,我们已经得到了每个元素在hash数组中的存放位置,如下图所示:但是这里存在一个问题,12和22这两个数据取模后的值都为2,这就产生了所谓的哈希冲突
浅谈自己对java中哈希表与HashSet的理解
解决哈希冲突的方式有很多种,像开发地址法,再哈希法,链地址法…。在java中大多采用的是链地址法来解决哈希冲突问题。网上有很多博客讲得很好,大家有兴趣可以去了解了解。

下面来说说自己对java中HashSet的理解:
set集合的特点:
1.存入集合的顺序和取出集合的顺序不一致
2.存入集合的元素没有重复

HashSet实现了Set接口,由哈希表(实际上是一个HashMap实例)支持,它不保证set的迭代循序。
作为set集合的实现类,HashSet是如何保证存入集合的元素不会重复呢?
其实是根据对象的hashCode和equals方法来决定的。
对于没有覆写hashCode和equals的类来说,当向HashSet中添加一个该类对象时,会首先调用该对象的hashCode方法得到一个int类型的哈希码值,该值(对应)该元素在哈希表中的存放位置。
若该位置已有元素存在,则会调用equals方法来比较这两个对象是否为同一对象。如果equals方法返回true,那么该元素不会存放在哈希表中,如果返回的是false,便会把该元素放入哈希表中。

所以当我们需要往HashSet中存放我们自定义的对象并保证其唯一性。就必须覆写hashCode和equals方法。

可能有些人会有这样的疑问,为什么往HashSet中存放字符串对象不会重复?
其实String类是覆写了hashCode和equals方法的。

String对象的哈希码根据以下公式计算:
浅谈自己对java中哈希表与HashSet的理解
这里 s[i] 是字符串的第 i 个字符,n 是字符串的长度,^ 表示求幂。(空字符串的哈希值为 0)。

String对象的equals方法:
当且仅当传入的参数不为 null,并且是与此对象具有相同字符序列的 String 对象时,结果才为 true。

以下是两个方法源码:
浅谈自己对java中哈希表与HashSet的理解浅谈自己对java中哈希表与HashSet的理解