Java中的Set集合

本文详细介绍了Java中的Set集合,包括HashSet的哈希表工作原理和元素唯一性的判断标准,LinkedHashSet的链表与哈希表数据结构及其有序特性,以及TreeSet的二叉树结构和排序机制。同时,提供了使用TreeSet存储自定义对象并进行排序的实践示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

set集合

特点:
存储是元素顺序和取出时元素顺序不一致;唯一,存入的元素唯一,不会出现重复

HashSet保证元素唯一性

HashSet 底层数据结构是哈希表. HashSet 不是线程安全的 集合元素可以是 null
哈希表:是一个元素为链表的数组,综合了数组和链表的优点 (像新华字典一样) (JDK1.7之前)

当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据 hashCode 值决定该对象在 HashSet 中的存储位置。
HashSet 集合判断两个元素相等的标准:
两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。
需要注意的是只有重写了Hashcode方法和equals方法才会保证元素唯一

在这里插入图片描述

LinkedHashSet的概述和使用

数据结构 有两个 链表和哈希表
链表保证有序 哈希表保证元素唯一

TreeSet

TreeSet集合的特点: 元素唯一,并且可以对元素进行排序
排序:
a: 自然排序
b: 使用比较器排序
到底使用的是哪一种的排序取决于,构造方法.
注意:使用TreeSet集合进行元素的自然排序,那么对元素有要求,要求这个元素
必须实现Comparable接口 否则无法进行自然排序
保证元素的唯一性是靠compareTo方法的返回值来确定如果返回0 表示两个元素相等
则不重复存储
TreeSet保证元素唯一和自然排序的原理和图解
二叉树的数据结构 先存入一个树根 分两个叉
存储元素时 跟树根比较 小的放在左边 大的放在右边
如果相等就不存储
取的时候按照 左中右的顺序来取
在这里插入图片描述
对排序二叉树,若按中序遍历就可以得到由小到大的有序序列。如图 1所示二叉树,中序遍历得:

{2,3,4,8,9,9,10,13,15,18}

TreeSet存储自定义对象并遍历练习

通过实现comparable接口,重写CompareTo方法进行排序

public  class Student implements Comparable<Student> {
    private String name;

    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public int compareTo(Student o) {

        int num = this.name.length() - o.name.length();
        int num2 = num == 0 ? this.name.compareTo(o.name) : num;
        num2=num2==0?this.age-o.age:num2;

        return num2;


    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Mytest {
    public static void main(String[] args) {
        Student s1 = new Student("晚饭", 22);
        Student s2 = new Student("晚饭", 23);
        Student s3 = new Student("吴大维吃是啊筛网", 33);
        Student s4 = new Student("我就打击我的娃", 21);
        Student s5 = new Student("菜徐坤", 33);
        TreeSet<Student> students = new TreeSet<Student>();
        students.add(s1);
        students.add(s2);
        students.add(s3);
        students.add(s4);
        students.add(s5);
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

也可以使用比较器进行排序

public class Mytest {
    public static void main(String[] args) {
        Student s1 = new Student("晚饭", 22);
        Student s2 = new Student("晚饭", 23);
        Student s3 = new Student("吴大维吃是啊筛网", 33);
        Student s4 = new Student("我就打击我的娃", 21);
        Student s5 = new Student("菜徐坤", 33);
        TreeSet<Student> students = new TreeSet<Student>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                int num = o1.getName().length() - o2.getName().length();
                int num2 = num == 0 ? o1.getName().compareTo(o2.getName()) : num;
                num2=num2==0?o1.getAge()-o2.getAge():num2;

                return num2;
            }
        });
        students.add(s1);
        students.add(s2);
        students.add(s3);
        students.add(s4);
        students.add(s5);
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

最后我们来做一个练习题
需求:编写一个程序,获取10个1至20的随机数,要求随机数不能重复。
并把最终的随机数输出到控制台。
分析:
a: 定义一个TreeSet集合
b: 产生随机数,把随机数添加到集合中
c: 判断集合的长度,使用while循环实现
代码:

public class Test1 {
    public static void main(String[] args) {
        Random random = new Random();
        TreeSet treeSet = new TreeSet();
        while (treeSet.size() < 10) {
            int num = random.nextInt(20) + 1;
            treeSet.add(num);
        }
        System.out.println(treeSet);
    }
}

因为使用的是TreeSet集合,所以已经帮我们排好序

<think>好的,用户想要寻找关于JavaSet集合的经典代码示例和练习。我需要先回忆一下Set集合的基本概念和常用实现类,比如HashSet、TreeSet和LinkedHashSet。根据引用内容,用户可能已经了解Set的基本特性,比如不允许重复元素,以及如何通过比较器或自然排序来排序元素。 首先,我应该提供一些基础的代码示例,展示如何创建Set、添加元素、遍历等操作。比如使用HashSet的简单例子,然后引入TreeSet的自然排序和定制排序。引用中提到需要比较器类,所以可能需要演示如何实现Comparator接口。 接下来,用户可能需要更复杂的练习,比如去重、集合运算(交集、并集、差集)或者结合泛型使用。引用中的泛型方法示例可能相关,可以展示如何在Set中使用泛型。 还要考虑实际应用场景,比如统计单词数量,处理学生成绩排名等。这些例子能帮助用户理解Set的实际用途。同时,引用中提到的TreeMap可能需要稍微提及,但重点应放在Set上。 需要确保代码语法正确,符合用户提供的引用中的格式。比如,比较器类的实现,自然排序通过Comparable接口,以及使用Lambda表达式简化代码。此外,用户可能需要了解线程安全的Set,所以可以提到ConcurrentSkipListSet,并给出示例。 最后,生成相关问题,帮助用户进一步学习,比如性能分析、线程安全的选择、比较器与Comparable的区别等。这些问题应基于提供的引用和常见的学习难点。 现在,整理这些思路,分步骤给出示例代码,并确保每个例子都有注释说明,符合用户的要求。同时,引用相关的引用内容,比如比较器类和自然排序的实现,以增强答案的可靠性。</think>以下是一些Java Set集合的经典代码示例和练习,结合了基础操作、应用场景和进阶技巧: ### 一、基础操作示例 1. **HashSet去重** ```java Set<String> cities = new HashSet<>(); Collections.addAll(cities, "北京", "上海", "广州", "北京", "深圳"); System.out.println(cities); // 输出:[北京, 上海, 广州, 深圳] 自动去重[^3] ``` 2. **TreeSet自然排序** ```java Set<Integer> scores = new TreeSet<>(); scores.add(85); scores.add(90); scores.add(78); System.out.println(scores); // 输出:[78, 85, 90] 自动排序 ``` ### 二、对象排序实践 3. **实现Comparable接口(自然排序)** ```java class Student implements Comparable<Student> { String name; int score; @Override public int compareTo(Student o) { return Integer.compare(this.score, o.score); // 按分数排序 } } Set<Student> stuSet = new TreeSet<>(); stuSet.add(new Student("王五", 90)); stuSet.add(new Student("李四", 85)); // 自动按分数升序排列 ``` 4. **使用Comparator定制排序**(引用[2]的Comparator实现) ```java Set<String> words = new TreeSet<>((s1, s2) -> s2.length() - s1.length()); // 按字符串长度降序排列 words.add("apple"); words.add("banana"); words.add("cat"); System.out.println(words); // 输出:[banana, apple, cat][^2] ``` ### 三、集合运算练习 5. **集合交集/并集/差集** ```java Set<Integer> setA = new HashSet<>(Arrays.asList(1,2,3)); Set<Integer> setB = new HashSet<>(Arrays.asList(2,3,4)); // 交集 setA.retainAll(setB); // 结果:[2,3] // 并集 setA.addAll(setB); // 结果:[1,2,3,4] // 差集 setA.removeAll(setB); // 结果:[1] ``` ### 四、高级应用示例 6. **统计单词频率** ```java String text = "this is a test text test"; Set<String> uniqueWords = new HashSet<>(Arrays.asList(text.split(" "))); System.out.println("Unique words count: " + uniqueWords.size()); ``` 7. **线程安全的有序集合** ```java Set<String> concurrentSet = new ConcurrentSkipListSet<>(); concurrentSet.add("A"); concurrentSet.add("C"); concurrentSet.add("B"); System.out.println(concurrentSet); // 保持线程安全的有序状态 ``` ### 推荐练习方向 1. 实现一个去重且保留插入顺序的集合(LinkedHashSet) 2. 编写比较器实现多字段排序(先按年龄降序,再按姓名升序) 3. 使用Stream API操作Set集合 4. 实现两个超大集合的高效交集运算
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值