当前位置: 首页 > news >正文

set集合(HashSet、LinkedHashSet、TreeSet)

目录

set集合:Java 中的 Set 是一种集合接口,属于 Java 集合框架(java.util 包)的一部分,它继承自 Collection 接口。Set 集合的核心特点是不允许包含重复元素,并且最多只能包含一个 null 元素(具体取决于HashSet、LinkedHashSet、TreeSet三个实现类)。

一、HashSet:

1、底层原理:

2、主要特性:

(1)无重复元素:添加重复元素时会被自动过滤(add() 方法返回 false),这是通过元素的 hashCode() 和 equals() 方法判断的。

(2)无序性:元素的存储顺序与添加顺序无关,且遍历顺序可能随时间变化(不保证稳定性).

(3)允许 null 元素:但最多只能存储一个 null(因为不允许重复)。

(4)高效性能:添加、删除、查询元素的平均时间复杂度为 O(1),这得益于哈希表的快速访问特性。

(5)非线程安全:多线程环境下需手动同步(如使用 Collections.synchronizedSet() 包装)。

3、初始化:

(1)public HashSet():创建一个默认为空的HashSet

(2)public HashSet(int initialCapacity, float loadFactor):initialCapacity(初始容量)指哈希表在创建时的初始桶(bucket)数量,默认值为 16。容量必须是 2 的幂次方(哈希表会自动调整为最接近的 2 的幂),这是为了优化哈希计算的效率。loadFactor(加载因子)是哈希表扩容的阈值比例,默认值为 0.75f,计算公式:扩容值 = 当前容量 × 加载因子。当元素数量超过阈值时,哈希表会自动扩容(容量翻倍),以减少哈希冲突。

(3)public HashSet(Collectionc):创建一个容器内容为c的集合。

4、常用方法:

(1)public boolean add(E e):向集合中添加元素。

(2)public boolean remove(Object o):集合中删除元素。

(3)public void clear():清空集合元素。

(4)public int size():返回集合中元素的数量。

(5)boolean addAll(Collectionc): 插入一个collection 集合,插入的时候只要成功的添加一个元素,返回值就为true。

(6)boolean isEmpty():判空

(7)boolean contains(Object o): 判断元素是否存在。

5、集合遍历:

二、LinkedHashSet:

1、底层原理:

2、主要特性:

(1)有序性:与 HashSet 的无序性不同,LinkedHashSet 会通过双向链表记录元素的插入顺序,因此遍历元素时会按照添加顺序输出。有序指的是元素放入的顺序

(2)无重复元素:和所有 Set 实现类一样,LinkedHashSet 不允许存储重复元素,判断重复的逻辑与 HashSet 一致(依赖 hashCode() 和 equals() 方法)。

(3)允许 null 元素:最多只能包含一个 null 元素。

(4)与HashSet 的初始化、常用方法、遍历一样

三、TreeSet:

1、底层实现:

2、主要特性:

(1)有序性:元素会按照自然排序(默认)或自定义排序规则进行排序,而非插入顺序。

(2)无重复元素:与所有 Set 实现类一样,不允许重复元素,重复元素会被自动过滤。

(3)不允许 null 元素:插入 null 会抛出 NullPointerException(因为需要比较元素大小)。

(4)性能:添加、删除、查询元素的时间复杂度为 O(log n),适合需要排序且频繁操作的场景。

(5)非线程安全:多线程环境下需手动同步(如使用 Collections.synchronizedSortedSet() 包装)。

3、初始化:

(1)public  TreeSet(): 构造一个空的有序set集合

(2)public TreeSet(Comparatorcomparator)构造一个传入排序规则的有序Set集合

(3)public TreeSet(Collectionc):构造一个集合元素为c的有序Set集合

4、Set集合如何过滤重复元素

四、HashSet、LinkedHashSet、TreeSet三者区别:


set集合:Java 中的 Set 是一种集合接口,属于 Java 集合框架(java.util 包)的一部分,它继承自 Collection 接口。Set 集合的核心特点是不允许包含重复元素,并且最多只能包含一个 null 元素(具体取决于HashSet、LinkedHashSet、TreeSet三个实现类)。

一、HashSet:

1、底层原理:

    HashSet 内部通过 HashMap 实现(维护一个 HashMap 实例):存储的元素被作为 HashMap 的 key,而 value 则是一个固定的空对象(PRESENT)。元素的去重逻辑依赖于 HashMap 的 key 不重复特性.

2、主要特性:
(1)无重复元素:添加重复元素时会被自动过滤(add() 方法返回 false),这是通过元素的 hashCode() 和 equals() 方法判断的。
(2)无序性:元素的存储顺序与添加顺序无关,且遍历顺序可能随时间变化(不保证稳定性).
(3)允许 null 元素:但最多只能存储一个 null(因为不允许重复)。
(4)高效性能:添加、删除、查询元素的平均时间复杂度为 O(1),这得益于哈希表的快速访问特性。
(5)非线程安全:多线程环境下需手动同步(如使用 Collections.synchronizedSet() 包装)。
3、初始化:
(1)public HashSet():创建一个默认为空的HashSet
(2)public HashSet(int initialCapacity, float loadFactor):initialCapacity(初始容量)指哈希表在创建时的初始桶(bucket)数量,默认值为 16。容量必须是 2 的幂次方(哈希表会自动调整为最接近的 2 的幂),这是为了优化哈希计算的效率。loadFactor(加载因子)是哈希表扩容的阈值比例,默认值为 0.75f,计算公式:扩容值 = 当前容量 × 加载因子。当元素数量超过阈值时,哈希表会自动扩容(容量翻倍),以减少哈希冲突。
(3)public HashSet(Collection<? extends E> c):创建一个容器内容为c的集合。
4、常用方法:
(1)public boolean add(E e):向集合中添加元素。
(2)public boolean remove(Object o):集合中删除元素。
(3)public void clear():清空集合元素。
(4)public int size():返回集合中元素的数量。
(5)boolean addAll(Collection<? extends E> c): 插入一个collection 集合,插入的时候只要成功的添加一个元素,返回值就为true。
(6)boolean isEmpty():判空
(7)boolean contains(Object o): 判断元素是否存在。
       HashSet<String> hs1 = new HashSet<>();//添加元素集合boolean b1 = hs1.add("曹操");hs1.add("周瑜");hs1.add("晁盖");boolean b2 = hs1.add("曹操");System.out.println("第一次添加元素:"+b1);System.out.println("第二次添加元素:"+b2);//快速生成list集合List<String> list = Arrays.asList("小乔","大乔","诸葛亮","晁盖");boolean b3 = hs1.addAll(list);  //添加元素集合,只要成功的添加一个元素,返回值就为trueSystem.out.println("添加集合是否成功:"+b3);System.out.println(hs1);System.out.println("元素个数为:"+hs1.size());System.out.println("元素是否存在:"+hs1.contains("小乔"));System.out.println("元素是否为空:"+hs1.isEmpty());//删除boolean b1=hs1.remove("小乔");System.out.println("删除元素是否成功:"+b1);System.out.println(hs1);//清空hs1.clear();System.out.println(hs1);
5、集合遍历:

迭代器遍历:Iterator<E> iterator()

        Iterator<String> itor = hs1.iterator();while(itor.hasNext()){System.out.println(itor.next());}System.out.println("===============");for (String str:hs1) {System.out.println(str);}

二、LinkedHashSet:

1、底层原理:

       基于 HashMap 实现(与 HashSet 相同),但额外通过链表记录元素顺序,本质是一个 "Linked HashMap" 的 key 集合。  

2、主要特性:
(1)有序性:与 HashSet 的无序性不同,LinkedHashSet 会通过双向链表记录元素的插入顺序,因此遍历元素时会按照添加顺序输出。有序指的是元素放入的顺序
(2)无重复元素:和所有 Set 实现类一样,LinkedHashSet 不允许存储重复元素,判断重复的逻辑与 HashSet 一致(依赖 hashCode() 和 equals() 方法)。
(3)允许 null 元素:最多只能包含一个 null 元素。
(4)与HashSet 的初始化、常用方法、遍历一样

三、TreeSet:

1、底层实现:

   TreeSet 内部依赖 TreeMap 实现(维护一个 TreeMap 实例):存储的元素被作为 TreeMap 的 key,value 是一个固定的空对象(PRESENT)。排序逻辑完全依赖 TreeMap 的 key 排序特性。元素必须可比较(要么实现 Comparable,要么提供 Comparator),否则会抛出 ClassCastException。排序规则需与 equals() 方法保持一致(即 compareTo() 返回 0 时,equals() 应返回 true),否则可能出现逻辑矛盾(如元素被视为不同但排序位置相同)。

2、主要特性:
(1)有序性:元素会按照自然排序(默认)或自定义排序规则进行排序,而非插入顺序。
(2)无重复元素:与所有 Set 实现类一样,不允许重复元素,重复元素会被自动过滤。
(3)不允许 null 元素:插入 null 会抛出 NullPointerException(因为需要比较元素大小)。
(4)性能:添加、删除、查询元素的时间复杂度为 O(log n),适合需要排序且频繁操作的场景。
(5)非线程安全:多线程环境下需手动同步(如使用 Collections.synchronizedSortedSet() 包装)。
3、初始化:
(1)public  TreeSet(): 构造一个空的有序set集合
(2)public TreeSet(Comparator<? super E> comparator)构造一个传入排序规则的有序Set集合
(3)public TreeSet(Collection<? extends E> c):构造一个集合元素为c的有序Set集合
4、Set集合如何过滤重复元素

核心原理:(1)hashCode() 方法:计算元素的哈希值,用于快速定位元素在底层数据结构(如哈希表)中的存储位置。两个相同的元素必须返回相同的哈希值。(2)equals() 方法:用于精确比较两个元素是否为 "逻辑上的相同元素"。当两个元素的哈希值相同时,会通过 equals() 进一步确认是否为重复元素。

自定义对象去重的关键:对于自定义类的对象,需同时重写 hashCode() 和 equals() 方法TreeSet 需保证排序逻辑与 equals() 一致),否则可能导致去重失效。

例如:

package com.yuan.treeset;import java.util.Comparator;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;public class Book implements Comparable<Book> {private String bookName;private String authorName;private int pageSize;private double price;public Book(String bookName, String authorName, int pageSize, double price) {this.bookName = bookName;this.authorName = authorName;this.pageSize = pageSize;this.price = price;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Book book = (Book) o;return pageSize == book.pageSize && Double.compare(book.price, price) == 0 && Objects.equals(bookName, book.bookName) && Objects.equals(authorName, book.authorName);}@Overridepublic String toString() {return "Book{" +"bookName='" + bookName + '\'' +", authorName='" + authorName + '\'' +", pageSize=" + pageSize +", price=" + price +'}' + "\n";}@Overridepublic int compareTo(Book o) {int result = this.pageSize - o.pageSize;if (result == 0) {return this.bookName.compareTo(o.bookName);}return result;}@Overridepublic int hashCode() {return Objects.hash(bookName, authorName, pageSize, price);}public String getBookName() {return bookName;}public void setBookName(String bookName) {this.bookName = bookName;}public String getAuthorName() {return authorName;}public void setAuthorName(String authorName) {this.authorName = authorName;}public int getPageSize() {return pageSize;}public void setPageSize(int pageSize) {this.pageSize = pageSize;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}
}class Demo01 {public static void main(String[] args) {//TreeSet是可排序的,且唯一的:// 在使用TreeSet时需要注意,一定要提供排序规则给对象(泛型类实现comparable接口或者对象提供Comparator对象)//1.无参的构造方法,排序规则使用泛型类型这个类定义的排序规则//2.有参构造TreeSet(Comparator comparator)排序比较规则按照传入的参数的规则为准Set<Book> set = new TreeSet<>();Book b1 = new Book("明朝那些事1", "当年明月1", 1231, 89.0);Book b2 = new Book("明朝那些事2", "当年明月2", 121, 89.0);Book b3 = new Book("明朝那些事3", "当年明月3", 11, 90.0);Book b4 = new Book("明朝那些事4", "当年明月1", 1231, 89.0);set.add(b1);set.add(b2);set.add(b3);set.add(b4);System.out.println(set);}}class Demo02 {public static void main(String[] args) {//如果泛型类型不是Comparable类型,必须要提供一个Comparator对象提供比较规则。Set<Book> set = new TreeSet<>(new Comparator<Book>() {@Overridepublic int compare(Book o1, Book o2) {//按照书的价格进行比较if(o1.getPrice()>o2.getPrice()){return 1;}else if (o1.getPrice() == o2.getPrice()) {return 0;}else {return -1;}}});Book b1 = new Book("明朝那些事1", "当年明月1", 1231, 89.0);Book b2 = new Book("明朝那些事2", "当年明月2", 121, 100.0);Book b3 = new Book("明朝那些事3", "当年明月3", 11, 90.0);Book b4 = new Book("明朝那些事4", "当年明月1", 1231, 89.0);set.add(b1);set.add(b2);set.add(b3);set.add(b4);System.out.println(set);}
}

四、HashSet、LinkedHashSet、TreeSet三者区别:

实现类排序特性底层结构时间复杂度(增删查)
HashSet无序哈希表O (1)(平均)
LinkedHashSet保持插入顺序哈希表 + 链表O (1)(平均)
TreeSet自然排序 / 自定义排序红黑树O(log n)

http://www.dtcms.com/a/296323.html

相关文章:

  • MySQL数据库迁移至国产数据库测试案例
  • 二、计算机网络技术——第6章:应用层
  • 深入理解 ThreadLocal:从原理到最佳实践
  • Vue实现地图图片动态轨迹组件,支持放大缩小重置,兼容触摸等
  • Uniapp中使用vue3语法
  • vue3升级了哪些重要功能
  • vite+vue3 工程-SVG图标配置使用指南——vite-plugin-svg-icons 插件
  • pytest中使用skip跳过某个函数
  • 4.1.2 XmlInclude 在 C# 中的作用及示例
  • 【软件与环境】--SSH连接远程服务器工具:FinalShell
  • C语言:详解文件操作
  • 【Java工程师面试全攻略】Day12:系统安全与高可用设计
  • 嵌入式linux I2C 设备开发调试 使用i2cget 工具失败的问题
  • JavaScript性能优化实战指南:从原理到最佳实践
  • Flink-1.19.0源码详解7-Flink集群端调度
  • 跨境支付入门~国际支付结算(区块链篇)
  • jina-embedding-v4 环境搭建全过程
  • 2025年“创新杯”(原钉钉杯) B题 详细建模思路
  • 牛客网刷题进阶挑战VL25——VL49
  • 【Linux网络编程】传输层协议 - UDP
  • 【数据结构初阶】--二叉树(二)
  • M²IV:面向大型视觉-语言模型中高效且细粒度的多模态上下文学习
  • BI 系统数据看板全解析:让数据可视化驱动业务决策
  • ESP32使用 vscode IDF 创建项目到烧录运行全过程
  • C++学习笔记(八:函数与变量)
  • 云原生架构下的服务器运维挑战与解决方案
  • 【CVPR 2025】即插即用,MobileMamba三阶段架构+Wavelet增强,颠覆轻量模型格局!
  • Qt Quick 3D渲染
  • 云端哨兵的智慧觉醒:Deepoc具身智能如何重塑工业无人机的“火眼金睛”
  • 5种最佳方法将iPhone语音备忘录传输到Mac