【Java】集合(二)Set

简介: 【Java】集合(二)Set

1.Set接口基本介绍

  • 无序:存取顺序不一致
  • 不重复:可以去除重复
  • 无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素

2.Set集合的实现类

  • HashSet:无序、不重复、无索引
  • LinkedHashSet: 有序、不重复、无索引
  • TreeSet: 可排序、不重复、无索引

3.Set接口中的常用方法

1)add:添加单个元素

2)remove:删除指定元素

3)contains:查找元素是否存在

4) size:获取元素个数

5)isEmpty:判断是否为空

6)clear:清空

7)addAll添加多个元素

8) containsAll:查找多个元素是否都存在

9) removeAll: 删除多个元素

4.HashSet

HashSet的全面说明

1)HashSet 的实现是依赖于HashMap的,HashSet 的值都是存储在HashMap中的。

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

3)不保证元素是有序的,取决于hash后,再确定索引的结果

4)不能重复对象

HsahSet底层原理

1)HashSet 底层是数组+链表+红黑树

2)添加一个元素时,先得到哈希值值-会转成-> 索引值(int index=(数组长度-1)&哈希值

3)找到存储数据表table,看这个索引位置是否已经存放的有元素

4)如果没有,直接加入

5)如果有 , 调用 equals 比较,如果相同,就放弃添加,如果不相同,则添加到最后在

6)Java8中,如果一条链表的元素个数到达 TREEIFY THRESHOLD(默认是 8),并且table的大小 >=MIN TREEIFY CAPACITY(默认64),就会进行树化(红黑树)

HashSet的扩容机制

1)HashSet底层是HashMap,第一次添加时,table 数组扩容到 16,临界值(threshold)是 16*加载因子loadFactor)是0.75 = 12

2)如果table 数组使用到了临界值 12,就会扩容到 16 * 2 = 32,新的临界值就是32*0.75 = 24,依次类推

3)在Java8中,如果一条链表的元素个数到达 TREEIFY THRESHOLD(默认是 8)并且table的大小 >=MIN TREEIFY CAPACITY(默认64)就会进行树化(红黑树),否则仍然采用数组扩容机制

5.LinkedHashSet

LinkedHashSet的全面说明

1)LinkedHashSet是HashSet的子类

2)LinkedHashSet底层是一个LinkedHashMap,底层维护了一个 数组+双向链表

3)LinkedHashSet根据元素的hashCode值来决定元素的存储位置,同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的。

4)LinkedHashSet不允许重复元素

LinkedHashSet的底层机制

1)在LinkedHastSet 中维护了一个hash表和双向链表( LinkedHashSet 有 head 和 tail )

2)每一个节点有 pre 和 next 属性,这样可以形成双向链表

3)在添加一个元素时,先求hash值,在求索引,确定该元素在hashtable的位置,然后将添加的元素加入到双向链表(如果已经存在,不添加[原则和hashset一样])

tail.next = newElement // 简单指定

newElement.pre = tail

tail = newEelment;

4)这样的话,我们遍历LinkedHashSet 也能确保插入顺序和遍历顺序一致

6.TreeSet

TreeSet集合的特点

  • 可排序、不重复、无索引
  • 底层基于红黑树实现排序,增删改查性能较好

TreeSet集合的自定义排序规则

TreeSet集合存储自定义类型的对象时,必须指定排序规则,支持如下两种方式来指定比较规则。

方式一

让自定义的类(如学生类)实现Comparable接口,重写里面的compareTo方法来指定比较规则。

方式二

通过调用TreeSet集合有参数构造器,可以设置Comparator对象 (比较器对象,用于指定比较规则)

public TreeSet(Comparator<? super E> comparator)

两种方式中,排序规则:

根据compareTo方法的返回值进行指定元素位置如

如果返回值为负数,表示当前存入的元素是较小值,存左边

如果返回值为0,表示当前存入的元素相等 ,不存

如果返回值为正数,表示当前存入的元素是较大值,存右边


注意: 如果类本身有实现Comparable接口,TreeSet集合同时也自带比较器,默认使用集合自带的比较器排序

7.说一下 HashSet、LinkedHashSet 和 TreeSet 三者的异同?

HashSet、LinkedHashSet 和 TreeSet 都是 Set 接口的实现类,都能保证元素唯一,并且都不是线程安全的。他们的不同点:

  • HashSet、LinkedHashSet 和 TreeSet 的主要区别在于底层数据结构不同:
  1. HashSet 的底层数据结构是哈希表(基于 HashMap 实现)
  2. LinkedHashSet 的底层数据结构是链表和哈希表,元素的插入和取出顺序满足 FIFO
  3. TreeSet 底层数据结构是红黑树,元素是有序的,排序的方式有自然排序和定制排序
  • 底层数据结构不同又导致这三者的应用场景不同:
  1. HashSet 用于不需要保证元素插入和取出顺序的场景
  2. LinkedHashSet 用于保证元素的插入和取出顺序满足 FIFO 的场景
  3. TreeSet 用于支持对元素自定义排序规则的场景
目录
相关文章
|
1天前
|
存储 安全 Java
Java一分钟之-集合框架进阶:Set接口与HashSet
【5月更文挑战第10天】本文介绍了Java集合框架中的`Set`接口和`HashSet`类。`Set`接口继承自`Collection`,特征是不允许重复元素,顺序不确定。`HashSet`是`Set`的实现,基于哈希表,提供快速添加、删除和查找操作,但无序且非线程安全。文章讨论了`HashSet`的特性、常见问题(如元素比较规则、非唯一性和线程安全性)以及如何避免这些问题,并提供了代码示例展示基本操作和自定义对象的使用。理解这些概念和注意事项能提升代码效率和可维护性。
9 0
|
1天前
|
存储 安全 算法
Java一分钟之-Java集合框架入门:List接口与ArrayList
【5月更文挑战第10天】本文介绍了Java集合框架中的`List`接口和`ArrayList`实现类。`List`是有序集合,支持元素重复并能按索引访问。核心方法包括添加、删除、获取和设置元素。`ArrayList`基于动态数组,提供高效随机访问和自动扩容,但非线程安全。文章讨论了三个常见问题:索引越界、遍历时修改集合和并发修改,并给出避免策略。通过示例代码展示了基本操作和安全遍历删除。理解并正确使用`List`和`ArrayList`能提升程序效率和稳定性。
7 0
|
1天前
|
Java 索引
【JAVA基础篇教学】第九篇:Java中Set详解说明
【JAVA基础篇教学】第九篇:Java中Set详解说明
|
3天前
|
存储 安全 算法
掌握Java并发编程:Lock、Condition与并发集合
掌握Java并发编程:Lock、Condition与并发集合
11 0
|
3天前
|
存储 安全 Java
深入理解Java集合框架
深入理解Java集合框架
9 0
|
9天前
|
存储 安全 Java
Java集合的分类有哪些?
Java中的集合就像一个容器,专门用来存储Java对象,这些对象可以是任意的数据类型,并且长度可变。这些集合类都位于java.util包中,在使用时一定要注意导包的问题,否则会出现异常。
35 10
|
12天前
|
Java 开发者
Java中三种Set的实现类的用法和区别
Java中三种Set的实现类的用法和区别
|
12天前
|
安全 Java
循环的时候去删除集合中的元素 java.util.ConcurrentModificationException
循环的时候去删除集合中的元素 java.util.ConcurrentModificationException
|
13天前
|
Java
【专栏】Java 8 的 Streams 提供了一种处理数据集合的新方式,增强了代码的可读性和可维护性
【4月更文挑战第28天】Java 8 的 Streams 提供了一种处理数据集合的新方式,增强了代码的可读性和可维护性。本文介绍了 Streams 的基本概念,如从数据源创建 Stream,以及中间和终端操作。通过过滤、映射、归并、排序、分组等案例,展示了 Streams 的使用,包括并行 Streams 提高效率。学习 Streams 可以提升代码质量和效率,文章鼓励读者在实际开发中探索更多 Streams 功能。
|
14天前
|
Java API 开发者
【专栏】Java 8的Stream API是处理集合数据的新方式,强调简洁和声明式编程
【4月更文挑战第27天】Java 8的Stream API是处理集合数据的新方式,强调简洁和声明式编程。它基于延迟执行和惰性求值,提供创建、中间操作(如filter、map)和终端操作(如forEach、collect)。示例展示了如何通过Stream排序、过滤、映射和聚合数据。