HashSet 的用法以及解决 HashSet 元素重复问题

JAVA herman 35浏览

我百度和谷歌分别搜索了一下 HashSet,发现谷歌上hashset用法、hashset是什么、hashset hashmap、hashset详解、hashset c#、hashset遍历、hashset使用、hashset重复、hashset set、hashset实现等这些关键词搜索的人比较多。百度上hashset的用法、HashSet()、HashSet的特点、LinkedHashSet、hashset数据结构图、hashset和arraylist、hashset是什么、HashSet java使用、hashset继承自这些关键词搜索的比较多。可见一些人对 HashSet 的使用还是存在疑惑的,所以结合我们公司的内部情况,我在这里分享一下我理解的 HashSet。

HashSet 和 HashMap 的区别

我们都知道 HashSet 是一个不允许存储重复元素的集合,它实现了 Set 接口。注意了,HashSet 是一个不允许存储重复元素的集合,并不是说不会存在重复元素。

你使用的不当,还是会造成重复元素的。最近我们公司里就发生了这样的事情,所以我需要给大家普及一下 HashSet 的相关知识。

对于 HashSet 而言,它是基于 HashMap 实现的,底层采用 HashMap 来保存元素,所以如果对 HashMap 比较熟悉了,那么学习 HashSet 就水到渠成了。

private transient HashMap<E,Object> map;

// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();

/**
 * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
 * default initial capacity (16) and load factor (0.75).
 */
public HashSet() {
    map = new HashMap<>();
}

通过上面的源码,你会发现 HashSet 主要有两个变量:

  • map :用于存放 add 进来的数据。
  • PRESENT :是所有写入 map 的 value 值。

然后添加元素的时候有一个 add 方法,源码如下:

public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

比较关键的就是这个 add() 方法。 可以看出它是将存放的对象当做了 HashMap 的健,value 都是相同的 PRESENT 。由于 HashMap 的 key 是不能重复的,所以每当有重复的值写入到 HashSet 时,value 会被覆盖,但 key 不会受到影响,这样就保证了 HashSet 中只能存放不重复的元素。

HashMap 中判断 Key 是否重复,用到了 Key 对象的 HashCode,根据上一章的知识《深度解读 Java 中的 equals()、==、hashCode()》,而 Key 对象,如果你没有重写 hashCode 方法的话,hashCode 值是根据内存地址换算出来的一个值。那么你 add 进 HashSet 的对象内存地址基本上都不一样,所以 HashSet 里存储的可能都是重复的元素,所以 HashSet 也就失去了意义。

由于 HashMap 的 put() 方法添加 key-value 对时,当新放入 HashMap 的 Entry 中 key 与集合中原有 Entry 的 key 相同(hashCode()返回值相等,通过 equals 比较也返回 true),新添加的 Entry 的 value 会将覆盖原来 Entry 的 value(HashSet 中的 value 都是PRESENT),但 key 不会有任何改变,因此如果向 HashSet 中添加一个已经存在的元素时,新添加的集合元素将不会被放入 HashMap中,原来的元素也不会有任何改变,这也就满足了 Set 中元素不重复的特性。

所以一些知识一定要掌握到位,不要只记住了前半部分,而忘记了后半部分。

有时候在我们的业务系统中判断对象时有时候需要的不是一种严格意义上的相等,而是一种业务上的相等。在这种情况下,原生的 equals 方法就不能满足我们的需求了,所以这个时候我们需要重写 equals 方法,来满足我们的业务系统上的需求。

根据我的经验,重写 hashCode 和 equals 基本上是成对出现的。

现在我留一个问题,HashSet 中是否可以添加 null 值?请关注微信公众号,留言评论!

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加QQ1群:135430763(2000人群已满),QQ2群:454796847,QQ3群:187424846。QQ群进群密码:xttblog,想加微信群的朋友,可以微信搜索:xmtxtt,备注:“xttblog”,添加助理微信拉你进群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作可添加助理微信进行沟通!

本文原文出处:业余草: » HashSet 的用法以及解决 HashSet 元素重复问题