JAVASE:Set集合

在 Java 中,Set 是一种不允许存储重复元素的集合接口,它继承自 Collection 接口。Set 通常用于存储唯一元素,如去重场景、数学集合运算等。

Set 接口的核心特性

元素唯一性:不允许存储重复元素,通过 equals() 和 hashCode() 方法判断元素是否重复。
无序性(部分有序):
HashSet:无序(不保证元素顺序)。
LinkedHashSet:按插入顺序排序。
TreeSet:按自然顺序或自定义比较器排序。
常用实现类:
HashSet:基于哈希表实现,性能最优,无序。
LinkedHashSet:继承自 HashSet,使用链表维护插入顺序。
TreeSet:基于红黑树实现,元素有序,不允许 null。

Set 的基本操作

以下是 Set 的常用方法示例:

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

public class SetExample {
    public static void main(String[] args) {
        // 创建 HashSet
        Set<String> names = new HashSet<>();

        // 添加元素
        names.add("Alice");
        names.add("Bob");
        names.add("Charlie");
        names.add("Alice"); // 重复元素会被自动过滤

        // 检查元素是否存在
        System.out.println("是否包含 Bob: " + names.contains("Bob")); // true

        // 删除元素
        names.remove("Charlie");
        System.out.println("删除后的集合: " + names); // [Alice, Bob]

        // 遍历集合
        System.out.println("遍历集合:");
        for (String name : names) {
            System.out.println(name);
        }

        // 使用 Lambda 表达式遍历
        names.forEach(name -> System.out.println("Hello, " + name));

        // 集合大小
        System.out.println("集合大小: " + names.size()); // 2

        // 判断集合是否为空
        System.out.println("集合是否为空: " + names.isEmpty()); // false

        // 清空集合
        names.clear();
        System.out.println("清空后的集合: " + names); // []
    }
}

LinkedHashSet 保持插入顺序

import java.util.LinkedHashSet;
import java.util.Set;

public class LinkedHashSetExample {
    public static void main(String[] args) {
        // 创建 LinkedHashSet
        Set<String> linkedSet = new LinkedHashSet<>();
        linkedSet.add("Banana");
        linkedSet.add("Apple");
        linkedSet.add("Cherry");

        // 按插入顺序输出
        System.out.println("LinkedHashSet(按插入顺序): " + linkedSet);
        // 输出: [Banana, Apple, Cherry]
    }
}

TreeSet 自然排序与自定义排序

import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        // 自然排序(字符串按字典序)
        TreeSet<String> naturalOrder = new TreeSet<>();
        naturalOrder.add("Charlie");
        naturalOrder.add("Alice");
        naturalOrder.add("Bob");

        System.out.println("自然排序: " + naturalOrder);
        // 输出: [Alice, Bob, Charlie]

        // 自定义排序(按字符串长度)
        TreeSet<String> lengthOrder = new TreeSet<>((s1, s2) -> 
            Integer.compare(s1.length(), s2.length())
        );
        lengthOrder.add("Apple");
        lengthOrder.add("Banana");
        lengthOrder.add("Kiwi");

        System.out.println("按长度排序: " + lengthOrder);
        // 输出: [Kiwi, Apple, Banana]
    }
}

Set 的集合运算

通过 retainAll()、removeAll() 等方法实现交集、并集、差集:

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

public class SetOperationsExample {
    public static void main(String[] args) {
        Set<Integer> set1 = new HashSet<>();
        set1.add(1);
        set1.add(2);
        set1.add(3);
        set1.add(4);

        Set<Integer> set2 = new HashSet<>();
        set2.add(3);
        set2.add(4);
        set2.add(5);
        set2.add(6);

        // 交集(set1 ∩ set2)
        Set<Integer> intersection = new HashSet<>(set1);
        intersection.retainAll(set2);
        System.out.println("交集: " + intersection); // [3, 4]

        // 并集(set1 ∪ set2)
        Set<Integer> union = new HashSet<>(set1);
        union.addAll(set2);
        System.out.println("并集: " + union); // [1, 2, 3, 4, 5, 6]

        // 差集(set1 - set2)
        Set<Integer> difference = new HashSet<>(set1);
        difference.removeAll(set2);
        System.out.println("差集: " + difference); // [1, 2]
    }
}

Set 实现类对比

特性 HashSet LinkedHashSet TreeSet
底层结构 哈希表 哈希表 + 链表 红黑树
元素顺序 无序 按插入顺序 按自然 / 自定义排序
允许 null 是 是 否
时间复杂度 O (1)(基本操作) O (1)(基本操作) O(log n)
线程安全 否 否 否

常见面试问题

HashSet 如何保证元素唯一性?
通过 hashCode() 和 equals() 方法判断元素是否重复。若两个元素 equals() 为 true,则它们的 hashCode() 必须相同。
TreeSet 与 HashSet 的区别?
TreeSet 有序且基于红黑树,HashSet 无序且基于哈希表;TreeSet 不允许 null,HashSet 允许一个 null。
HashSet 与 LinkedHashSet 的性能差异?
两者基本操作时间复杂度均为 O (1),但 LinkedHashSet 因维护链表会稍慢,不过遍历时性能更好。
如何实现线程安全的 Set?
使用 Collections.synchronizedSet(new HashSet<>()) 或 CopyOnWriteArraySet。
使用自定义对象作为 Set 元素
若使用自定义对象,需重写 hashCode() 和 equals() 方法:

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

class Person {
    private final String name;
    private final int age;

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

    // 重写 hashCode 和 equals
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && name.equals(person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

public class CustomObjectInSet {
    public static void main(String[] args) {
        Set<Person> people = new HashSet<>();
        people.add(new Person("Alice", 25));
        people.add(new Person("Bob", 30));
        people.add(new Person("Alice", 25)); // 重复元素,不会被添加

        System.out.println(people); // [Person{name='Alice', age=25}, Person{name='Bob', age=30}]
    }
}

掌握 Set 的核心实现类及其适用场景,能有效解决去重和集合运算等问题。合理重写 hashCode() 和 equals() 是使用自定义对象的关键。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java永无止境

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值