Java Set集合知识点

一、Set接口概述

1.1 Set接口特点

import java.util.*;

public class SetOverview {

public static void main(String[] args) {

// Set接口的特点:

// 1. 不允许重复元素(基于equals()和hashCode()判断)

// 2. 最多允许一个null元素

// 3. 不保证元素的顺序(某些实现如TreeSet保证排序)

// 4. 没有get(index)方法(因为无序)

Set<String> set = new HashSet<>();

// 添加元素

System.out.println("添加Apple: " + set.add("Apple")); // true

System.out.println("添加Banana: " + set.add("Banana")); // true

System.out.println("重复添加Apple: " + set.add("Apple")); // false

set.add("Orange");

set.add("Grape");

set.add(null); // 允许一个null

System.out.println("Set集合: " + set);

System.out.println("大小: " + set.size());

System.out.println("是否包含Banana: " + set.contains("Banana"));

System.out.println("是否为空: " + set.isEmpty());

}

}

二、Set的主要实现类

2.1 HashSet(哈希集合)

import java.util.*;

public class HashSetDemo {

public static void main(String[] args) {

// HashSet:基于HashMap实现

// 特点:无序、允许null、查找效率高(O(1))

Set<String> hashSet = new HashSet<>();

// 1. 基本操作

hashSet.add("Java");

hashSet.add("Python");

hashSet.add("C++");

hashSet.add("JavaScript");

hashSet.add("Java"); // 重复,不会被添加

System.out.println("HashSet: " + hashSet);

// 2. 批量操作

Set<String> anotherSet = new HashSet<>();

anotherSet.add("Go");

anotherSet.add("Rust");

anotherSet.add("Java");

hashSet.addAll(anotherSet); // 并集

System.out.println("添加后: " + hashSet);

// 3. 删除操作

hashSet.remove("C++");

hashSet.removeIf(lang -> lang.startsWith("J")); // Java 8+

System.out.println("删除后: " + hashSet);

// 4. 遍历方式

// 增强for循环

for (String lang : hashSet) {

System.out.print(lang + " ");

}

System.out.println();

// 迭代器

Iterator<String> iterator = hashSet.iterator();

while (iterator.hasNext()) {

System.out.print(iterator.next() + " ");

}

System.out.println();

// forEach方法

hashSet.forEach(lang -> System.out.print(lang + " "));

System.out.println();

// 5. 构造方法示例

Set<Integer> numbers = new HashSet<>(20); // 指定初始容量

numbers.addAll(Arrays.asList(1, 2, 3, 4, 5));

// 从已有集合创建

Set<String> copySet = new HashSet<>(hashSet);

// 6. 性能测试

Set<Integer> largeSet = new HashSet<>();

long start = System.nanoTime();

for (int i = 0; i < 100000; i++) {

largeSet.add(i);

}

long addTime = System.nanoTime() - start;

System.out.println("\n添加100000个元素耗时: " + (addTime / 1000000) + "ms");

start = System.nanoTime();

boolean contains = largeSet.contains(50000);

long searchTime = System.nanoTime() - start;

System.out.println("查找元素耗时: " + searchTime + "ns");

}

}

2.2 LinkedHashSet(有序哈希集合)

import java.util.*;

public class LinkedHashSetDemo {

public static void main(String[] args) {

// LinkedHashSet:继承自HashSet,基于LinkedHashMap实现

// 特点:维护插入顺序,迭代顺序与插入顺序一致

Set<String> linkedHashSet = new LinkedHashSet<>();

// 按顺序添加元素

linkedHashSet.add("First");

linkedHashSet.add("Second");

linkedHashSet.add("Third");

linkedHashSet.add("Fourth");

linkedHashSet.add("Fifth");

linkedHashSet.add("Second"); // 重复,不会添加

System.out.println("LinkedHashSet(保持插入顺序): " + linkedHashSet);

// 遍历会按照插入顺序

System.out.print("遍历顺序: ");

for (String s : linkedHashSet) {

System.out.print(s + " ");

}

System.out.println();

// 访问顺序示例(LinkedHashMap的特性)

// LinkedHashSet本身不支持访问顺序,但LinkedHashMap支持

// 如果需要访问顺序,需要使用LinkedHashMap

// LinkedHashSet构造方法

Set<Integer> numbers = new LinkedHashSet<>(Arrays.asList(3, 1, 4, 1, 5, 9));

System.out.println("数字(保持插入顺序): " + numbers);

// 性能对比

testPerformance();

}

private static void testPerformance() {

int size = 100000;

// HashSet

Set<Integer> hashSet = new HashSet<>();

long start = System.nanoTime();

for (int i = 0; i < size; i++) {

hashSet.add(i);

}

long hashSetTime = System.nanoTime() - start;

// LinkedHashSet

Set<Integer> linkedHashSet = new LinkedHashSet<>();

start = System.nanoTime();

for (int i = 0; i < size; i++) {

linkedHashSet.add(i);

}

long linkedHashSetTime = System.nanoTime() - start;

System.out.println("\n性能对比(添加" + size + "个元素):");

System.out.println("HashSet: " + (hashSetTime / 1000000) + "ms");

System.out.println("LinkedHashSet: " + (linkedHashSetTime / 1000000) + "ms");

System.out.println("LinkedHashSet稍慢,因为需要维护链表结构");

}

}

2.3 TreeSet(树集合)

import java.util.*;

public class TreeSetDemo {

public static void main(String[] args) {

// TreeSet:基于TreeMap(红黑树)实现

// 特点:元素自动排序,不允许null(因为需要比较)

// 1. 自然排序(元素必须实现Comparable接口)

TreeSet<String> treeSet = new TreeSet<>();

treeSet.add("Banana");

treeSet.add("Apple");

treeSet.add("Orange");

treeSet.add("Grape");

treeSet.add("Cherry");

System.out.println("TreeSet(自动排序): " + treeSet);

// 2. 自定义排序

TreeSet<Integer> numbers = new TreeSet<>(Collections.reverseOrder());

numbers.addAll(Arrays.asList(5, 2, 8, 1, 9, 3));

System.out.println("降序TreeSet: " + numbers);

// 3. TreeSet特有方法

System.out.println("\n--- TreeSet特有方法 ---");

// 第一个和最后一个

System.out.println("第一个元素: " + treeSet.first());

System.out.println("最后一个元素: " + treeSet.last());

// 小于/大于某个元素

System.out.println("小于'Grape'的最大元素: " + treeSet.lower("Grape"));

System.out.println("大于'Grape'的最小元素: " + treeSet.higher("Grape"));

// 子集

System.out.println("从Apple到Grape(包含): " +

treeSet.subSet("Apple", true, "Grape", true));

System.out.println("从Apple到Grape(不包含Grape): " +

treeSet.subSet("Apple", true, "Grape", false));

// 头集和尾集

System.out.println("小于'Orange'的元素: " + treeSet.headSet("Orange"));

System.out.println("大于等于'Orange'的元素: " + treeSet.tailSet("Orange"));

// 4. 使用Comparator

TreeSet<Person> people = new TreeSet<>(Comparator

.comparing(Person::getAge)

.thenComparing(Person::getName));

people.add(new Person("Alice", 25));

people.add(new Person("Bob", 30));

people.add(new Person("Charlie", 25)); // 年龄相同,按名字排序

people.add(new Person("David", 28));

System.out.println("\n按年龄排序: " + people);

// 5. 遍历

System.out.print("正向遍历: ");

for (String fruit : treeSet) {

System.out.print(fruit + " ");

}

System.out.println();

System.out.print("反向遍历: ");

Iterator<String> descendingIterator = treeSet.descendingIterator();

while (descendingIterator.hasNext()) {

System.out.print(descendingIterator.next() + " ");

}

System.out.println();

}

static class Person {

String name;

int age;

Person(String name, int age) {

this.name = name;

this.age = age;

}

String getName() { return name; }

int getAge() { return age; }

@Override

public String toString() {

return name + "(" + age + ")";

}

}

}

三、Set的数学运算

3.1 集合运算(并集、交集、差集)

import java.util.*;

public class SetOperations {

public static void main(String[] args) {

Set<Integer> set1 = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));

Set<Integer> set2 = new HashSet<>(Arrays.asList(4, 5, 6, 7, 8));

System.out.println("集合A: " + set1);

System.out.println("集合B: " + set2);

// 1. 并集(Union)

Set<Integer> union = new HashSet<>(set1);

union.addAll(set2);

System.out.println("并集 A∪B: " + union);

// 2. 交集(Intersection)

Set<Integer> intersection = new HashSet<>(set1);

intersection.retainAll(set2);

System.out.println("交集 A∩B: " + intersection);

// 3. 差集(Difference)

Set<Integer> difference = new HashSet<>(set1);

difference.removeAll(set2);

System.out.println("差集 A-B: " + difference);

// 4. 对称差集(Symmetric Difference)- 在A或B中,但不同时在A和B中

Set<Integer> symmetricDifference = new HashSet<>(union);

symmetricDifference.removeAll(intersection);

System.out.println("对称差集: " + symmetricDifference);

// 5. 子集判断

Set<Integer> subset = new HashSet<>(Arrays.asList(2, 3));

System.out.println("{2,3}是否是A的子集: " + set1.containsAll(subset));

// 6. 相等判断

Set<Integer> set3 = new HashSet<>(Arrays.asList(5, 4, 3, 2, 1));

System.out.println("A和{5,4,3,2,1}是否相等: " + set1.equals(set3));

// 7. 补集(Complement)示例

Set<Integer> universalSet = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));

Set<Integer> complement = new HashSet<>(universalSet);

complement.removeAll(set1);

System.out.println("A在全集{1..10}中的补集: " + complement);

}

}

四、自定义对象在Set中的使用

4.1 重写equals()和hashCode()

import java.util.*;

public class CustomObjectInSet {

public static void main(String[] args) {

// 对于自定义对象,要正确使用Set,必须重写equals()和hashCode()

Set<Student> studentSet = new HashSet<>();

Student s1 = new Student("001", "Alice", 20);

Student s2 = new Student("002", "Bob", 21);

Student s3 = new Student("001", "Alice", 20); // 与s1相同

System.out.println("添加s1: " + studentSet.add(s1)); // true

System.out.println("添加s2: " + studentSet.add(s2)); // true

System.out.println("添加s3(与s1相同): " + studentSet.add(s3)); // false

System.out.println("学生集合: " + studentSet);

System.out.println("集合大小: " + studentSet.size());

// TreeSet中的自定义对象必须实现Comparable或提供Comparator

TreeSet<Student> treeSet = new TreeSet<>(Comparator

.comparing(Student::getAge)

.thenComparing(Student::getName));

treeSet.add(s1);

treeSet.add(s2);

treeSet.add(new Student("003", "Charlie", 19));

System.out.println("\nTreeSet(按年龄排序): " + treeSet);

}

static class Student {

private String id;

private String name;

private int age;

public Student(String id, String name, int age) {

this.id = id;

this.name = name;

this.age = age;

}

// 重写equals()方法

@Override

public boolean equals(Object o) {

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;

Student student = (Student) o;

return Objects.equals(id, student.id);

}

// 重写hashCode()方法

@Override

public int hashCode() {

return Objects.hash(id);

}

// 重写toString()方法

@Override

public String toString() {

return name + "(" + id + ", " + age + ")";

}

// Getter方法

public String getId() { return id; }

public String getName() { return name; }

public int getAge() { return age; }

}

}

五、线程安全的Set实现

5.1 同步包装和并发Set

import java.util.*;

import java.util.concurrent.*;

public class ThreadSafeSets {

public static void main(String[] args) throws InterruptedException {

System.out.println("=== 线程安全的Set实现 ===\n");

// 1. Collections.synchronizedSet(传统方式)

Set<String> synchronizedSet = Collections.synchronizedSet(new HashSet<>());

// 遍历时需要手动同步

synchronized(synchronizedSet) {

for (String s : synchronizedSet) {

System.out.println(s);

}

}

// 2. CopyOnWriteArraySet(适合读多写少的场景)

// 写操作时复制整个数组,读操作不需要锁

CopyOnWriteArraySet<String> copyOnWriteSet = new CopyOnWriteArraySet<>();

copyOnWriteSet.add("Item1");

copyOnWriteSet.add("Item2");

copyOnWriteSet.addIfAbsent("Item1"); // 如果不存在则添加

System.out.println("CopyOnWriteArraySet: " + copyOnWriteSet);

// 遍历时是安全的

for (String item : copyOnWriteSet) {

System.out.println(item);

copyOnWriteSet.add("NewItem"); // 不会影响当前遍历

}

// 3. ConcurrentHashMap.newKeySet()(Java 8+)

Set<String> concurrentSet = ConcurrentHashMap.newKeySet();

concurrentSet.add("Concurrent1");

concurrentSet.add("Concurrent2");

System.out.println("ConcurrentHashMap KeySet: " + concurrentSet);

// 4. 性能测试

testPerformance();

}

private static void testPerformance() throws InterruptedException {

int threads = 10;

int iterations = 10000;

System.out.println("\n=== 性能测试 ===");

// HashSet(非线程安全)

Set<Integer> hashSet = new HashSet<>();

testSetPerformance(hashSet, "HashSet", threads, iterations);

// synchronizedSet

Set<Integer> syncSet = Collections.synchronizedSet(new HashSet<>());

testSetPerformance(syncSet, "SynchronizedSet", threads, iterations);

// CopyOnWriteArraySet

Set<Integer> cowSet = new CopyOnWriteArraySet<>();

testSetPerformance(cowSet, "CopyOnWriteArraySet", threads, iterations);

// ConcurrentHashMap KeySet

Set<Integer> concurrentSet = ConcurrentHashMap.newKeySet();

testSetPerformance(concurrentSet, "ConcurrentKeySet", threads, iterations);

}

private static void testSetPerformance(Set<Integer> set, String name,

int threads, int iterations)

throws InterruptedException {

ExecutorService executor = Executors.newFixedThreadPool(threads);

long startTime = System.currentTimeMillis();

// 创建多个任务并发执行

List<Callable<Void>> tasks = new ArrayList<>();

for (int t = 0; t < threads; t++) {

final int threadId = t;

tasks.add(() -> {

for (int i = 0; i < iterations; i++) {

int value = threadId * iterations + i;

set.add(value);

set.contains(value);

if (set.size() > 1000) {

set.remove(value - 500);

}

}

return null;

});

}

// 执行所有任务

executor.invokeAll(tasks);

executor.shutdown();

executor.awaitTermination(1, TimeUnit.MINUTES);

long endTime = System.currentTimeMillis();

System.out.printf("%-25s: %5d ms, 大小: %d%n",

name, endTime - startTime, set.size());

}

}

六、Set的性能比较和选择策略

6.1 性能比较

import java.util.*;

public class SetPerformanceComparison {

public static void main(String[] args) {

int size = 100000;

System.out.println("=== Set实现类性能比较 ===\n");

// HashSet

Set<Integer> hashSet = new HashSet<>();

long hashSetTime = testAddAndContains(hashSet, size);

// LinkedHashSet

Set<Integer> linkedHashSet = new LinkedHashSet<>();

long linkedHashSetTime = testAddAndContains(linkedHashSet, size);

// TreeSet

Set<Integer> treeSet = new TreeSet<>();

long treeSetTime = testAddAndContains(treeSet, size);

System.out.println("添加和查找 " + size + " 个元素的耗时:");

System.out.println("HashSet: " + hashSetTime + "ms");

System.out.println("LinkedHashSet: " + linkedHashSetTime + "ms");

System.out.println("TreeSet: " + treeSetTime + "ms");

System.out.println("\n=== 内存占用比较 ===");

printMemoryUsage();

}

private static long testAddAndContains(Set<Integer> set, int size) {

long start = System.currentTimeMillis();

// 添加元素

for (int i = 0; i < size; i++) {

set.add(i);

}

// 查找元素

for (int i = 0; i < size; i++) {

set.contains(i);

}

return System.currentTimeMillis() - start;

}

private static void printMemoryUsage() {

Runtime runtime = Runtime.getRuntime();

Set<Object> hashSet = new HashSet<>();

Set<Object> linkedHashSet = new LinkedHashSet<>();

Set<Object> treeSet = new TreeSet<>();

// 添加一些元素

for (int i = 0; i < 10000; i++) {

hashSet.add("String_" + i);

linkedHashSet.add("String_" + i);

treeSet.add("String_" + i);

}

System.gc();

long hashSetMemory = runtime.totalMemory() - runtime.freeMemory();

System.gc();

long linkedHashSetMemory = runtime.totalMemory() - runtime.freeMemory();

System.gc();

long treeSetMemory = runtime.totalMemory() - runtime.freeMemory();

System.out.println("HashSet内存占用: ~" + (hashSetMemory/1024) + "KB");

System.out.println("LinkedHashSet内存占用: ~" + (linkedHashSetMemory/1024) + "KB");

System.out.println("TreeSet内存占用: ~" + (treeSetMemory/1024) + "KB");

}

}

6.2 选择策略

public class SetSelectionGuide {

/*

Set实现类选择指南:

  1. HashSet(最常用)
  • 场景:需要快速查找,不关心顺序

  • 优点:添加、删除、查找最快(O(1))

  • 缺点:无序

  1. LinkedHashSet
  • 场景:需要保持插入顺序

  • 优点:保持插入顺序,查找速度快

  • 缺点:比HashSet稍慢,内存占用稍大

  1. TreeSet
  • 场景:需要排序或范围查找

  • 优点:自动排序,支持范围操作

  • 缺点:操作较慢(O(log n)),不允许null

  1. CopyOnWriteArraySet
  • 场景:读多写少的并发环境

  • 优点:读操作不需要锁

  • 缺点:写操作性能差,内存占用大

  1. ConcurrentHashMap.newKeySet()
  • 场景:高并发环境

  • 优点:并发性能好

  • 缺点:没有范围操作

*/

public static void main(String[] args) {

// 示例:根据不同场景选择Set

// 场景1:存储不重复的用户ID,不关心顺序

System.out.println("场景1:用户ID集合(快速查找)");

Set<String> userIds = new HashSet<>();

// 场景2:记录用户访问页面的顺序

System.out.println("场景2:用户访问历史(保持顺序)");

Set<String> visitHistory = new LinkedHashSet<>();

// 场景3:按分数排序的学生集合

System.out.println("场景3:学生成绩排名(需要排序)");

Set<StudentScore> studentScores = new TreeSet<>(Comparator

.comparing(StudentScore::getScore).reversed());

// 场景4:多线程共享的配置集合

System.out.println("场景4:多线程配置集合");

Set<String> configSet = ConcurrentHashMap.newKeySet();

}

static class StudentScore {

String name;

int score;

// ... 省略构造方法和getter

}

}

七、Java 8+ 新特性在Set中的应用

7.1 Stream API操作Set

import java.util.*;

import java.util.stream.*;

public class SetStreamOperations {

public static void main(String[] args) {

Set<Integer> numbers = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));

System.out.println("原始集合: " + numbers);

// 1. 过滤

Set<Integer> evenNumbers = numbers.stream()

.filter(n -> n % 2 == 0)

.collect(Collectors.toSet());

System.out.println("偶数集合: " + evenNumbers);

// 2. 映射

Set<String> squaredStrings = numbers.stream()

.map(n -> n + "^2=" + (n * n))

.collect(Collectors.toCollection(LinkedHashSet::new)); // 保持顺序

System.out.println("平方映射: " + squaredStrings);

// 3. 排序

List<Integer> sortedList = numbers.stream()

.sorted()

.collect(Collectors.toList());

System.out.println("排序后: " + sortedList);

// 4. 统计

long count = numbers.stream().count();

int sum = numbers.stream().mapToInt(Integer::intValue).sum();

Optional<Integer> max = numbers.stream().max(Integer::compare);

Optional<Integer> min = numbers.stream().min(Integer::compare);

System.out.printf("统计: 数量=%d, 和=%d, 最大=%s, 最小=%s%n",

count, sum, max.orElse(null), min.orElse(null));

// 5. 查找

Optional<Integer> firstEven = numbers.stream()

.filter(n -> n % 2 == 0)

.findFirst();

System.out.println("第一个偶数: " + firstEven.orElse(null));

// 6. 匹配

boolean allEven = numbers.stream().allMatch(n -> n % 2 == 0);

boolean anyEven = numbers.stream().anyMatch(n -> n % 2 == 0);

boolean noneNegative = numbers.stream().noneMatch(n -> n < 0);

System.out.printf("匹配: 全偶数=%s, 有偶数=%s, 无负数=%s%n",

allEven, anyEven, noneNegative);

// 7. 去重(Set本身就去重,这里演示其他用途)

List<Integer> withDuplicates = Arrays.asList(1, 2, 2, 3, 3, 3, 4);

Set<Integer> distinct = withDuplicates.stream()

.collect(Collectors.toSet());

System.out.println("去重: " + distinct);

// 8. 并行流

Set<Integer> parallelProcessed = numbers.parallelStream()

.map(n -> n * 2)

.collect(Collectors.toSet());

System.out.println("并行处理: " + parallelProcessed);

// 9. 分组

Map<String, Set<Integer>> grouped = numbers.stream()

.collect(Collectors.groupingBy(

n -> n % 2 == 0 ? "偶数" : "奇数",

Collectors.toSet()

));

System.out.println("分组: " + grouped);

// 10. 创建不可变Set(Java 9+)

Set<String> immutableSet = Set.of("A", "B", "C");

// immutableSet.add("D"); // 抛出UnsupportedOperationException

System.out.println("不可变Set: " + immutableSet);

// 11. 复制Set

Set<String> original = new HashSet<>(Arrays.asList("X", "Y", "Z"));

Set<String> copy = Set.copyOf(original); // Java 10+

System.out.println("复制Set: " + copy);

}

}

八、Set实用工具类

8.1 Set工具类示例

import java.util.*;

public class SetUtils {

/**

* 计算两个Set的并集

*/

public static <T> Set<T> union(Set<T> set1, Set<T> set2) {

Set<T> result = new HashSet<>(set1);

result.addAll(set2);

return result;

}

/**

* 计算两个Set的交集

*/

public static <T> Set<T> intersection(Set<T> set1, Set<T> set2) {

Set<T> result = new HashSet<>(set1);

result.retainAll(set2);

return result;

}

/**

* 计算两个Set的差集(set1 - set2)

*/

public static <T> Set<T> difference(Set<T> set1, Set<T> set2) {

Set<T> result = new HashSet<>(set1);

result.removeAll(set2);

return result;

}

/**

* 计算两个Set的对称差集

*/

public static <T> Set<T> symmetricDifference(Set<T> set1, Set<T> set2) {

Set<T> union = union(set1, set2);

Set<T> intersection = intersection(set1, set2);

return difference(union, intersection);

}

/**

* 判断set1是否是set2的子集

*/

public static <T> boolean isSubset(Set<T> set1, Set<T> set2) {

return set2.containsAll(set1);

}

/**

* 判断set1是否是set2的真子集

*/

public static <T> boolean isProperSubset(Set<T> set1, Set<T> set2) {

return isSubset(set1, set2) && set1.size() < set2.size();

}

/**

* 将Set转换为排序的List

*/

public static <T extends Comparable<T>> List<T> toSortedList(Set<T> set) {

List<T> list = new ArrayList<>(set);

Collections.sort(list);

return list;

}

/**

* 获取Set中的最大元素

*/

public static <T extends Comparable<T>> Optional<T> max(Set<T> set) {

return set.stream().max(Comparable::compareTo);

}

/**

* 获取Set中的最小元素

*/

public static <T extends Comparable<T>> Optional<T> min(Set<T> set) {

return set.stream().min(Comparable::compareTo);

}

/**

* 随机获取Set中的一个元素

*/

public static <T> Optional<T> randomElement(Set<T> set) {

if (set.isEmpty()) {

return Optional.empty();

}

int randomIndex = new Random().nextInt(set.size());

Iterator<T> iterator = set.iterator();

for (int i = 0; i < randomIndex; i++) {

iterator.next();

}

return Optional.of(iterator.next());

}

/**

* 测试工具类

*/

public static void main(String[] args) {

Set<Integer> A = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));

Set<Integer> B = new HashSet<>(Arrays.asList(4, 5, 6, 7, 8));

System.out.println("集合A: " + A);

System.out.println("集合B: " + B);

System.out.println("并集: " + union(A, B));

System.out.println("交集: " + intersection(A, B));

System.out.println("差集(A-B): " + difference(A, B));

System.out.println("对称差集: " + symmetricDifference(A, B));

System.out.println("A是B的子集: " + isSubset(A, B));

System.out.println("{1,2}是A的真子集: " + isProperSubset(new HashSet<>(Arrays.asList(1, 2)), A));

Set<Integer> unsorted = new HashSet<>(Arrays.asList(5, 2, 8, 1, 3));

System.out.println("排序后的列表: " + toSortedList(unsorted));

System.out.println("最大值: " + max(unsorted).orElse(null));

System.out.println("最小值: " + min(unsorted).orElse(null));

System.out.println("随机元素: " + randomElement(unsorted).orElse(null));

}

}

总结

核心知识点:

  1. Set接口特性:不允许重复、无序(某些实现有序)、最多一个null

  2. HashSet vs LinkedHashSet vs TreeSet:根据是否需要排序或保持插入顺序选择

  3. equals()和hashCode():自定义对象必须正确重写才能在Set中正常工作

  4. 线程安全:使用并发集合或同步包装

  5. 集合运算:并集、交集、差集、对称差集

最佳实践:

· 大多数情况使用HashSet

· 需要保持插入顺序时使用LinkedHashSet

· 需要排序或范围操作时使用TreeSet

· 多线程环境使用并发集合

· 自定义对象必须正确实现equals()和hashCode()

· 合理利用Stream API简化操作

相关推荐
郝学胜-神的一滴2 小时前
Linux多线程编程:深入理解pthread_cancel函数
linux·服务器·开发语言·c++·软件工程
廋到被风吹走2 小时前
【Java】JPA
java·开发语言·oracle
Trouvaille ~2 小时前
【C++篇】让错误被温柔对待(下):异常高级特性与最佳实践
运维·开发语言·c++·异常·raii·编程实践·基础入门
计算机毕设指导62 小时前
基于微信小程序的设备报修系统【源码文末联系】
java·spring boot·微信小程序·小程序·tomcat·maven·intellij-idea
没有bug.的程序员2 小时前
服务治理体系:从零到一的全景落地指南
java·开发语言·数据库·微服务·架构
毕设源码-郭学长2 小时前
【开题答辩全过程】以 基于SpringBoot的足球运动员训练计划管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
kylezhao20192 小时前
C#上位机开发数据持久化:xml数据导入导出
xml·开发语言·c#
-Xie-2 小时前
Redis(十六)——底层数据结构(一)
java·数据结构·redis
小园子的小菜2 小时前
深入理解Trie树:敏感词过滤的核心原理与实现思路
算法