Set 集合详解:无序、不重复的集合!

举报
喵手 发表于 2025/08/24 21:05:33 2025/08/24
【摘要】 开篇语哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,...

开篇语

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

在 Java 中,Set 集合是一种非常常用的集合类型,它与 List 不同,最大的特点是无序且不重复。如果你需要存储一组不重复的数据,同时不关心元素的顺序,Set 就是一个理想的选择。在本文中,我们将详细分析 Set 集合的实现原理,讲解 HashSetLinkedHashSetTreeSet 的特点,以及它们在实际项目中的应用场景。

1. HashSet 实现原理

HashSet 是 Java 中最常用的 Set 集合实现类。它基于哈希表(HashMap)实现,存储元素时依赖于元素的哈希值。下面我们来详细了解一下 HashSet 的实现原理。

1.1 HashSet 的基本特点

  • 无序HashSet 不保证元素的顺序,因此存入集合的元素不一定按照插入顺序排列。
  • 不重复HashSet 不允许存储重复元素。如果尝试加入一个重复元素,添加操作会被忽略。
  • 线程不安全HashSet 是线程不安全的,如果多线程环境下使用它,需要外部进行同步控制。

1.2 HashSet 的底层原理

HashSet 通过 HashMap 来实现。具体来说,HashSet 的每个元素都被存储为 HashMap 的键,而 HashMap 的值是一个固定的常量对象。这使得 HashSet 能够通过哈希表来保证元素的快速查找,同时保证不重复。

  • 在向 HashSet 中添加元素时,HashSet 会计算元素的哈希值,并将元素作为 HashMap 的键添加到哈希表中。
  • 如果插入的元素已经存在(即哈希值相同且 equals() 方法返回 true),则该元素不会被重复添加。
import java.util.HashSet;

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

        System.out.println(set);  // 输出 [Orange, Banana, Apple]
    }
}

1.3 HashSet 的性能

  • 查找、删除和添加的时间复杂度:由于 HashSet 基于哈希表,它的查找、删除和添加操作的平均时间复杂度为 O(1),非常高效。

2. LinkedHashSet 特点

LinkedHashSetHashSet 的一个子类,它结合了哈希表和链表的特点。与 HashSet 相比,LinkedHashSet 的主要特点是维护了元素的插入顺序

2.1 LinkedHashSet 的基本特点

  • 有序LinkedHashSet 保证元素的插入顺序,遍历时会按照元素被添加到集合中的顺序返回。
  • 不重复:与 HashSet 一样,LinkedHashSet 不允许重复元素。
  • 线程不安全LinkedHashSet 也是线程不安全的,适用于单线程环境或需要手动同步的场景。

2.2 LinkedHashSet 的底层原理

LinkedHashSet 内部使用了 HashMap 来存储数据,并且使用一个双向链表来维护元素的插入顺序。每次插入元素时,LinkedHashSet 会通过哈希表来保证元素的唯一性,同时通过链表来记录插入顺序。

import java.util.LinkedHashSet;

public class LinkedHashSetExample {
    public static void main(String[] args) {
        LinkedHashSet<String> set = new LinkedHashSet<>();
        set.add("Apple");
        set.add("Banana");
        set.add("Orange");

        System.out.println(set);  // 输出 [Apple, Banana, Orange]
    }
}

2.3 LinkedHashSet 的性能

  • 查找、删除和添加的时间复杂度LinkedHashSet 由于是基于哈希表实现的,查找、删除和添加操作的平均时间复杂度为 O(1)。
  • 插入顺序:由于 LinkedHashSet 维护了元素的插入顺序,因此它的插入、删除、访问顺序有一定的额外开销。

3. TreeSet 和排序

TreeSetSet 接口的另一个实现类,它基于 TreeMap 实现,元素按自然顺序或自定义顺序进行排序。

3.1 TreeSet 的基本特点

  • 有序TreeSet 中的元素是有序的,默认按照元素的自然顺序进行排序,也可以通过传入 Comparator 对象来实现自定义排序。
  • 不重复:与其他 Set 实现一样,TreeSet 也不允许重复元素。
  • 线程不安全TreeSet 是线程不安全的。

3.2 TreeSet 的底层原理

TreeSet 底层是基于红黑树实现的,红黑树是一种自平衡的二叉查找树,能够保证插入、删除、查找等操作的时间复杂度为 O(log n)。

  • TreeSet 中,元素按升序排列(使用 ComparableComparator 进行排序)。
  • 插入元素时,TreeSet 会根据元素的大小关系进行位置排序。
import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<Integer> set = new TreeSet<>();
        set.add(10);
        set.add(20);
        set.add(5);
        set.add(15);

        System.out.println(set);  // 输出 [5, 10, 15, 20]
    }
}

3.3 自定义排序

你可以通过传入自定义的 Comparator 来实现自定义排序规则。例如,按降序排列元素:

import java.util.TreeSet;
import java.util.Comparator;

public class CustomSortExample {
    public static void main(String[] args) {
        TreeSet<Integer> set = new TreeSet<>(Comparator.reverseOrder());
        set.add(10);
        set.add(20);
        set.add(5);
        set.add(15);

        System.out.println(set);  // 输出 [20, 15, 10, 5]
    }
}

3.4 TreeSet 的性能

  • 查找、删除和添加的时间复杂度:由于 TreeSet 基于红黑树实现,它的查找、删除和添加操作的时间复杂度为 O(log n),比 HashSet 的 O(1) 慢,但它具有排序功能。

4. Set 集合的应用场景

Set 集合广泛应用于需要存储不重复元素的场景,它在以下几种应用中表现得尤为出色:

4.1 数据去重

在处理大量数据时,我们通常需要去重操作。Set 集合可以有效地保证元素不重复。例如,去除列表中的重复元素:

import java.util.HashSet;
import java.util.List;
import java.util.ArrayList;

public class RemoveDuplicatesExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Apple");
        list.add("Banana");
        list.add("Apple");
        list.add("Orange");

        HashSet<String> set = new HashSet<>(list);
        System.out.println(set);  // 输出 [Apple, Banana, Orange]
    }
}

4.2 统计唯一元素

Set 适用于统计唯一元素。例如,统计一组数据中有多少种不同的元素:

import java.util.HashSet;

public class UniqueElementsExample {
    public static void main(String[] args) {
        String[] data = {"apple", "banana", "apple", "orange", "banana"};
        HashSet<String> set = new HashSet<>();
        
        for (String item : data) {
            set.add(item);
        }
        
        System.out.println("Unique elements: " + set.size());  // 输出 Unique elements: 3
    }
}

4.3 排序元素

如果需要有序的元素(例如按升序或自定义规则排序),可以使用 TreeSet,它会自动排序。例如,存储一组数字并按升序排序:

import java.util.TreeSet;

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

        System.out.println(set);  // 输出 [1, 3, 5, 9]
    }
}

4.4 快速查找和删除

Set 的查找、删除操作通常比 List 更高效,尤其在使用 HashSet 时。它适用于需要频繁查找和删除元素的场景。

总结

  • HashSet:基于哈希表实现,存储无序、不可重复的元素,性能高,但不保证顺序。
  • LinkedHashSet:继承自 HashSet,同时保持元素的插入顺序,适用于需要有序存储的场景。
  • TreeSet:基于红黑树实现,自动排序,适用于需要排序的场景,但性能稍逊色。

Set 集合的应用非常广泛,特别适用于去重、统计唯一元素、排序和高效查找等场景。在实际开发中,根据具体需求选择合适的 Set 实现类,能够大大提高程序的性能和可维护性。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。


版权声明:本文由作者原创,转载请注明出处,谢谢支持!

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。