Set集合详解Java

Set 接口有三个实现类

HashSet

底层是由 HashMap 实现,不允许集合中有重复的值,使用该方式时需要重写 equals()和 hashCode()方法
HashSet(Hash 表)哈希表边存放的是哈希值。HashSet 存储元素的顺序并不是按照存入时的顺序(和 List 显然不同) 而是按照哈希值来存的所以取数据也是按照哈希值取得。元素的哈希值是通过元素的hashcode 方法来获取的, HashSet 首先判断两个元素的哈希值,如果哈希值一样,接着会比较equals 方法 如果 equls 结果为 true ,HashSet 就视为同一个元素。如果 equals 为 false 就不是同一个元素。
哈希值相同 equals 为 false 的元素是怎么存储呢,就是在同样的哈希值下顺延(可以认为哈希值相同的元素放在一个哈希桶中)。也就是哈希一样的存一列。如图 1 表示 hashCode 值不相同的情况;图 2 表示 hashCode 值相同,但 equals 不相同的情况。
HashSet是由一个hash表来实现的,因此,它的元素是无序的。add(),remove(),contains()方法的时间复杂度是O(1)。
另一方面,TreeSet是由一个树形的结构来实现的,它里面的元素是有序的。因此,add(),remove(),contains()方法的时间复杂度是O(logn)。

LinkedHashSet

继承与 HashSet,同时又基于 LinkedHashMap 来进行实现,底
层使用的是 LinkedHashMp
对 于 LinkedHashSet 而言,它继承与 HashSet、又基于 LinkedHashMap 来实现的。
LinkedHashSet 底层使用 LinkedHashMap 来保存所有元素,它继承与 HashSet,其所有的方法操作上又与 HashSet 相同,因此 LinkedHashSet 的实现上非常简单,只提供了四个构造方法,并
通过传递一个标识参数,调用父类的构造器,底层构造一个 LinkedHashMap 来实现,在相关操作上与父类 HashSet 的操作相同,直接调用父类 HashSet 的方法即可。

TreeSet(二叉树)

  1. TreeSet()是使用二叉树的原理对新 add()的对象按照指定的顺序排序(升序、降序),每增
    加一个对象都会进行排序,将对象插入的二叉树指定的位置。
  2. Integer 和 String 对象都可以进行默认的 TreeSet 排序,而自定义类的对象是不可以的,自
    己定义的类必须实现 Comparable 接口,并且覆写相应的 compareTo()函数,才可以正常使
    用。
  3. 在覆写 compare()函数时,要返回相应的值才能使 TreeSet 按照一定的规则来排序
  4. 比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。

set集合的底层实现

set集合的底层实现
a.底层数据结构是哈希表,线程是不同步的。无序,高效;
b.HashSet 集合保证元素唯一性:通过元素的 hashCode 方法和 equals 方法完成的。
当元素的 hashCode 值相同时,才继续判断元素的 equals 是否为 true。
如果为 true,那么视为相同元素,不存。如果为 false,那么存储。
如果 hashCode 值不同,那么不判断 equals,从而提高对象比较的速度。

Set 注重独一无二的性质,该体系集合用于存储无序(存入和取出的顺序不一定相同)元素,值不能重
复。对象的相等性本质是对象 hashCode 值(java 是依据对象的内存地址计算出的此序号)判断
的,如果想要让两个不同的对象视为相等的,就必须覆盖 Object 的 hashCode 方法和 equals 方法。

Set元素不重复的原因

在 Java 的集合框架中,Set 接口是一种不允许元素重复的集合。它的实现类(如 HashSet、TreeSet、LinkedHashSet 等)使用了不同的机制来保证元素的唯一性。

  1. HashSet:基于哈希表实现。当将元素添加到 HashSet 中时,会根据元素的哈希码确定其存储位置,如果该位置已经存在其他元素,则通过比较确定是否重复。因此,对于相同的元素,其哈希码必须相等,同时需要重写元素类的 hashCode() 和 equals() 方法。
  2. TreeSet:基于红黑树实现。元素在 TreeSet 中按照比较器(Comparator)或元素自然顺序进行排序,保证元素有序。在插入元素时,会根据比较结果来判断是否重复。因此,对于相同的元素,其 compareTo() 方法或比较器的 compare() 方法必须返回 0。
  3. LinkedHashSet:基于哈希表和链表实现。它同时维护了一个哈希表和一个双向链表,哈希表用于快速查找元素,链表用于保持元素的插入顺序。因此,保证了元素的唯一性和插入顺序。
    无论是哪种实现类,它们都是通过特定的数据结构和算法来确保元素的唯一性。在使用 Set 接口时,需要保证元素类正确实现了 hashCode() 和 equals() 方法(或者 Comparable 接口的 compareTo() 方法),以便于集合判断元素的相等性和唯一性。

HashSet 如何检查重复

当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对象加入的 位置,同时也会与其他加入的对象的 hashcode 值作比较,如果没有相符的 hashcode,
HashSet 会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 equals()方法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会 让加入操作成功。 在 openjdk8 中,HashSet 的 add()方法只是简单的调用了 HashMap 的 put()方法,并 且判断了一下返回值以确保是否有重复元素。 也就是说,在 openjdk8 中,实际上无论
HashSet 中是否已经存在了某元素,HashSet 都会直接插入,只是会在 add()方法的返回值 处告诉我们插入前是否存在相同元素。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

思静语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值