java set(超详细)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

在 Java 集合框架中,Set 是一个重要的接口,它提供了一种无需维护元素顺序且不允许重复的集合类型。无论是处理数据去重、唯一性校验,还是构建高效的数据结构,Set 都是开发者不可或缺的工具。对于编程初学者和中级开发者而言,掌握 Set 的核心概念、实现类以及应用场景,不仅能提升代码效率,还能为后续学习更复杂的集合类型打下基础。本文将从基础到实践,逐步解析 Java Set 的原理与用法,并通过案例帮助读者深入理解其实现细节。


一、Set 的基本概念与核心特性

1.1 什么是 Set?

Set 是 Java 集合框架中的一个接口,继承自 Collection 接口。它的核心特性包括:

  • 无序性:元素的存储和遍历顺序通常不固定(但某些实现类可能保留插入顺序)。
  • 唯一性:不允许重复元素,即所有元素的 hashCode()equals() 方法返回值必须唯一。
  • 无索引:无法通过索引直接访问元素,需通过迭代器或增强型 for 循环遍历。

比喻:可以将 Set 想象为一个装满不同种类卡片的抽屉,每张卡片的内容(元素)必须唯一,且抽屉不会记录卡片插入的顺序。

1.2 Set 的实现类

Java 提供了多个 Set 接口的实现类,每个实现类针对不同的使用场景优化:
| 实现类 | 核心特性 |
|-------------------|--------------------------------------------------------------------------|
| HashSet | 基于哈希表实现,元素无序且不保证插入顺序,性能高效。 |
| TreeSet | 基于红黑树实现,元素按自然顺序或自定义排序规则排列。 |
| LinkedHashSet | 继承 HashSet,同时维护插入顺序,遍历时元素按插入顺序返回。 |

选择建议

  • 需要高性能的添加、删除操作时,优先选择 HashSet
  • 需要元素按特定顺序排列时,选择 TreeSet
  • 需要兼顾唯一性和插入顺序时,选择 LinkedHashSet

二、Set 的实现类详解与代码示例

2.1 HashSet:高效无序集合

HashSetSet 接口中使用最广泛的实现类,其底层基于 哈希表(Hash Table) 实现。哈希表通过计算元素的哈希值(hashCode())快速定位元素,因此 HashSet 的添加、删除和查找操作的时间复杂度均为 O(1)(平均情况)。

核心特性:

  • 无序性:元素的存储顺序与插入顺序无关。
  • 唯一性:通过 hashCode()equals() 方法判断元素是否重复。

代码示例

import java.util.HashSet;  
import java.util.Set;  

public class HashSetExample {  
    public static void main(String[] args) {  
        Set<String> hashSet = new HashSet<>();  
        hashSet.add("Apple");  
        hashSet.add("Banana");  
        hashSet.add("Apple"); // 重复元素不会被添加  

        System.out.println("HashSet 元素:" + hashSet);  
        // 输出可能为:[Banana, Apple](顺序不固定)  
    }  
}  

哈希冲突与解决

当两个不同对象的 hashCode() 值相同时,称为 哈希冲突。此时,HashSet 会通过对象的 equals() 方法进一步判断是否重复。若 equals() 返回 true,则视为重复元素,仅保留一个;否则,将元素存入哈希表的“链表”或“红黑树”结构中。


2.2 TreeSet:有序且唯一的集合

TreeSet 通过 红黑树(Red-Black Tree) 维护元素的有序性。其核心特性包括:

  • 自动排序:元素按自然顺序(Comparable 接口)或自定义比较器(Comparator 接口)排列。
  • 唯一性:与 HashSet 相同,不允许重复元素。

代码示例

import java.util.TreeSet;  

public class TreeSetExample {  
    public static void main(String[] args) {  
        TreeSet<Integer> treeSet = new TreeSet<>();  
        treeSet.add(5);  
        treeSet.add(3);  
        treeSet.add(8);  
        treeSet.add(1);  

        System.out.println("TreeSet 元素:" + treeSet);  
        // 输出:[1, 3, 5, 8](按自然顺序排列)  
    }  
}  

自定义排序规则

若需按特定逻辑排序,可通过 Comparator 实现:

TreeSet<String> treeSet = new TreeSet<>((s1, s2) -> s2.length() - s1.length());  
treeSet.add("Java");  
treeSet.add("C++");  
treeSet.add("Python");  
// 输出:[Python, Java, C++](按字符串长度降序排列)  

2.3 LinkedHashSet:有序与高效的平衡

LinkedHashSet 继承自 HashSet,同时通过 双向链表 记录元素的插入顺序。其性能与 HashSet 接近,但遍历时会按元素插入顺序返回。

代码示例

import java.util.LinkedHashSet;  

public class LinkedHashSetExample {  
    public static void main(String[] args) {  
        LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();  
        linkedHashSet.add("Red");  
        linkedHashSet.add("Green");  
        linkedHashSet.add("Blue");  

        System.out.println("LinkedHashSet 元素:" + linkedHashSet);  
        // 输出:[Red, Green, Blue](与插入顺序一致)  
    }  
}  

三、Set 的常用操作与代码实践

3.1 基础操作

添加与删除元素

Set<String> set = new HashSet<>();  
set.add("Hello"); // 添加元素  
set.remove("Hello"); // 删除元素  

判断元素是否存在

if (set.contains("World")) {  
    System.out.println("元素存在");  
}  

遍历 Set

for (String element : set) {  
    System.out.println(element);  
}  

3.2 Set 在实际场景中的应用

场景 1:数据去重

假设需要统计一段文本中所有唯一单词:

public static Set<String> extractUniqueWords(String text) {  
    Set<String> words = new HashSet<>();  
    // 假设 text 已分割为单词列表  
    for (String word : text.split("\\s+")) {  
        words.add(word);  
    }  
    return words;  
}  

场景 2:唯一性校验

在注册系统中验证用户名是否唯一:

public boolean isUsernameAvailable(String username, Set<String> existingUsers) {  
    return !existingUsers.contains(username);  
}  

四、Set 与 List 的对比与选择

4.1 核心差异

特性ListSet
顺序支持,按插入顺序存储无序(部分实现类如 LinkedHashSet 支持插入顺序)
重复元素允许重复禁止重复
典型场景需要按索引访问或保留顺序需要唯一性或快速查找

4.2 常见误区

  • 误区:认为 Set 的遍历顺序永远随机。
    澄清HashSet 的顺序看似随机,实则是由哈希表的底层结构决定;LinkedHashSetTreeSet 则有明确的顺序规则。

五、总结与进阶建议

通过本文,读者应已掌握以下内容:

  1. Set 接口的核心特性及其实现类的差异。
  2. HashSetTreeSetLinkedHashSet 的底层原理与使用场景。
  3. Set 在实际开发中的典型应用案例。

进阶方向

  • 深入学习哈希表、红黑树等数据结构的原理。
  • 探索 SetMap 的关联(如 HashMap 的键集合即为 Set)。
  • 实践 Set 在多线程环境下的线程安全实现(如 CopyOnWriteArraySet)。

通过持续练习和实践,开发者将能灵活运用 Java Set 解决复杂问题,提升代码的效率与可维护性。


希望本文能成为您理解 Java Set 的起点,后续可结合具体项目需求进一步探索!

最新发布