Java集合HashSet介绍

本文介绍了Java集合中的HashSet,它基于HashMap实现,不允许重复元素。HashSet内部使用K, V模式,其中V为Object。重写hashcode和equals方法至关重要,避免因只重写hashcode而导致的重复元素问题。当元素数量超过0.75*数组长度时,HashSet会进行扩容,链表节点数达到9时会树化。在JDK1.7中,多线程环境下可能导致链表死循环,但在JDK1.8中已通过尾插法避免此问题。" 132440556,19671270,C语言实现快速排序算法,"['排序算法', 'c语言', '编程', '算法实现']

Set接口

HashSet

  • 底层HashMap

  • 实际上是K,V模式,只不过V放的是一个统一的Object

  • 可以存放null值,但是只能有一个null值

  • 不能有重复元素

  • 这里面需要考虑到hashcode与equals方法的重写

    如果放入Set集合的元素只重写hashcode而不重写equals,会导致重复元素添加,源码如下

  • 此时认为hashcode是相等的,这两个元素到同一个hash槽里面

    并且执行遍历链表寻找插入位置的操作。

  • 插入操作源码具体流程,首先调用map的put方法,put方法调用hash方法对key的hashcode再进行hash处理,以减少哈希碰撞,然后再调用putVal方法,将key和Object传入

  • putValue方法首先判断tab数组是否为空,如果为空则会调用resize方法去把table初始化,

    如果节点数量大于0.75*数组长度,则会进行扩容

    初始化完成之后寻找hash槽,并且插入,如果一个槽里面的链表大于9个的时候会进行树化,但是树化前会进行判断,判断总节点个数是否小于64,如过小于64,则再调用resize方法进行2倍(加载因子)扩容。如果树化之后树的元素小于6,则会再次降级为链表

  • 为什么HashMap链表会形成死循环

    准确的讲应该是 JDK1.7 的 HashMap 链表会有死循环的可能,因为JDK1.7是采用的头插法,在多线程环境下有可能会使链表形成环状,从而导致死循环。JDK1.8做了改进,用的是尾插法,不会产生死循环。

 

### HashSet 的基本概念 HashSetJava 集合框架中的一个实现类,其底层实际上是通过 HashMap 来实现的,这意味着它的底层数据结构是数组、链表以及红黑树的组合[^2]。这种结构使得 HashSet 在读取和查找操作上具有较高的效率。 ### HashSet 的主要特性 - **唯一性**:HashSet 不允许重复元素的存在,这是通过内部的 HashMap 来保证的,当两个对象的 `equals` 方法返回 true 并且它们的 `hashCode` 相同时,认为这两个对象是相等的。 - **允许 null 元素**:可以向 HashSet 中添加一个 null 元素。 - **非线程安全**:HashSet 不是一个线程安全的集合类,如果需要在多线程环境中使用,应该采取额外的同步措施。 ### HashSet 的性能特点 - **内存开销**:相比于 ArrayList,HashSet 的内存开销更大,因为它基于 HashMap 实现。 - **增删查的时间复杂度**:对于 HashSet 而言,增加、删除和查找元素的时间复杂度均为 O(1),这表明这些操作的平均时间是常数级别的[^3]。 ### 使用场景 由于 HashSet 提供了快速的查找和插入功能,它非常适合用于需要快速访问元素的场景。例如,在需要检查某个元素是否存在的情况下,使用 HashSet 可以大大提高程序的效率。 ### 示例代码 以下是一个简单的 HashSet 使用示例: ```java import java.util.HashSet; public class HashSetExample { public static void main(String[] args) { // 创建一个 HashSet HashSet<String> set = new HashSet<>(); // 添加元素 set.add("Apple"); set.add("Banana"); set.add("Cherry"); // 尝试添加重复元素 boolean isAdded = set.add("Apple"); // 返回 false,因为 "Apple" 已经存在 // 输出结果 System.out.println("Set contains Apple: " + isAdded); System.out.println("Set size: " + set.size()); } } ``` ### 注意事项 - 在使用 HashSet 时需要注意其非线程安全的性质,如果在多线程环境中使用,应该考虑使用同步机制。 - HashSet 中的元素是无序的,这意味着迭代顺序可能与插入顺序不同。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值