回答
Set 接口是通过元素之间的比较来保证元素唯一性的,不同的实现类比较的方式不一样:
HashSet
和LinkedHashSet
是基于哈希表实现的。他们是通过元素的hashCode()
与equals()
来保证的,只有当hashCode()
相同且equals()
方法返回true
时,两个对象才被视为相同的,这样来保证元素的唯一性。TreeSet
是基于红黑树实现的。它是通过元素实现的Comparable
接口或者在新建 TreeSet 时传入的Comparator
来保证元素的唯一性。
详解
在 Java 中 Set
接口是一个不包含重复元素的集合,它主要有两类实现:
HashSet
和LinkedHashSet
是基于哈希表实现的。TreeSet
是基于红黑树实现的。
他们是通过如下方式来保证元素的唯一性的。
HashSet
HashSet
使用哈希表来存储元素,底层是基于 HashMap 来实现的。当向 HashSet 中添加元素时,它首先计算出该元素的 hashcode 值,然后在通过扰动计算和按位与的方式计算出该元素的位置,若这个位置为空,则添加进去,若不为空,则通过 equals()
比较两者是否相同,如果相同,就不添加,不同,则找一个空位置添加。所以 HashSet
是通过 hashCode()
与 equals()
来保证的,只有当 hashCode()
相同且 equals()
方法返回 true
时,两个对象才被视为相同的,这样就保证了元素的唯一性。
LinkedHashSet
是 HashSet
的子类,只不过它是有序的,保证了迭代元素的顺序就是元素的插入顺序,元素的唯一值保证与 HashSet
一致。
关于 hashCode()
和 equals()
请阅读这篇文章:
为什么重写 equals() 就一定要重写 hashCode()
TreeSet
TreeSet
实现 SortedSet
接口,使用红黑树结构来存储元素。元素的唯一性有两种方式保证:
- 使用自然顺序,需要元素实现
Comparable
接口,并重写了compareTo()
。 - 在创建
TreeSet
的时候提供Comparator
来保证。
如果两个元素通过比较器被认为是相等的,那么只有一个元素会被存储在 TreeSet
中。
其实 Set 接口的元素唯一性是由元素的比较来实现的,只不过不同的实现,它的比较方式不同罢了。
扩展
HashSet 、LinkedHashSet、TreeSet 有什么区别?
一、内部结构不同
HashSet
基于哈希表实现,底层是通过HashMap
实现的。LinkedHashSet
也是基于哈希表实现的,但它使用了一个双向链表来维护元素的插入顺序,底层是通过LinkedHashMap
实现的。TreeSet
基于红黑树实现,底层是通过TreeMap
实现的。
二、功能不同
HashSet
只保证元素的唯一性。LinkedHashSet
保证元素的唯一性,同时也维持了元素的插入顺序。TreeSet
保证了元素的唯一性,同时还支持按照元素的自然顺序进行排序,或者根据创建TreeSet
时提供的Comparator
进行排序。
三、性能
HashSet
> LinkedHashSet
> TreeSet
。
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。