Java集合框架(List/Set/Queue)核心总结与代码示例

目录

写在前面:

一、List

1、ArrayList

底层结构:

核心特点:

适用场景:

注意事项:

示例代码:

2、LinkedList

底层结构:

核心特点:

适用场景:

注意事项:

示例代码:

3、Vector、Stack

底层结构:

核心特点:

适用场景:

替代方案:

[4. CopyOnWriteArrayList](#4. CopyOnWriteArrayList)

底层结构:

核心特点:

适用场景:

注意事项:

示例代码:

二、Set

1、HashSet

底层结构:

核心特点:

适用场景:

注意事项:

示例代码:

2、LinkedHashSet

底层结构:

核心特点:

适用场景:

示例代码(保持插入顺序的去重):

3、TreeSet

底层结构:

核心特点:

适用场景:

示例代码:

4、CopyOnWriteArraySet

底层结构:

核心特点:

注意事项:

三、Queue

1、ArrayDeque

底层结构:

核心特点:

注意事项:

示例代码(常用方法):

[2. LinkedList(既是List,也是Queue)](#2. LinkedList(既是List,也是Queue))

3、PriorityQueue(优先队列)

底层结构:

核心特点:

注意事项:

示例代码(自定义排序):

4、ConcurrentLinkedQueue(高并发非阻塞)

底层结构:

核心特点:

5、LinkedBlockingQueue(最常用的阻塞队列)

底层结构:

核心特点:

注意事项:

6、ArrayBlockingQueue(固定容量的阻塞队列)

底层结构:

核心特点:

注意事项:

7、DelayQueue(延迟队列)

底层结构:

核心特点:

注意事项:


写在前面:

本文总结了Java集合(Collection)的各种常用实现类,这些是平时开发常用到的,在这里总结夯实基础,建议在阅读的时候自己亲自动手实践熟练下这些常用实现类。

一、List

1、ArrayList

底层结构:

基于动态数组(Object[])实现。

核心特点:

内存连续,支持快速的随机访问(通过索引 get/set 的时间复杂度为 O(1))。但在数组中间插入或删除元素时,需要移动后续所有元素,开销较大。

适用场景:

需要频繁通过下标读取数据的场景

注意事项:

默认初始容量为 10,扩容时会增加 50% 的容量并进行数组复制。如果提前知道数据量,建议在创建时指定初始容量,以减少扩容带来的性能损耗。

示例代码:

java 复制代码
 // 创建 ArrayList
        ArrayList<String> list = new ArrayList<>();
        
        // 添加元素
        list.add("Apple");
        list.add("Banana");
        list.add("Cherry");
        list.add("Date");
        list.add("Elderberry");
        System.out.println("初始列表: " + list);
        
        // 在指定位置插入
        list.add(1, "Avocado");
        System.out.println("插入后: " + list);
        
        // 获取元素
        String first = list.get(0);
        System.out.println("第一个元素: " + first);
        
        // 修改元素
        list.set(2, "Blueberry");
        System.out.println("修改后: " + list);
        
        // 检查元素是否存在
        boolean contains = list.contains("Apple");
        System.out.println("是否包含 Apple: " + contains);
        
        // 获取大小
        int size = list.size();
        System.out.println("列表大小: " + size);
        
        // 遍历 - for-each
        System.out.print("for-each 遍历: ");
        for (String item : list) {
            System.out.print(item + " ");
        }
        System.out.println();
        
        // 遍历 - Iterator
        System.out.print("Iterator 遍历: ");
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + " ");
        }
        System.out.println();
        
        // 查找索引
        int index = list.indexOf("Cherry");
        System.out.println("Cherry 的索引: " + index);
        
        // 删除元素
        list.remove("Date");
        System.out.println("删除 Date 后: " + list);
        
        list.remove(0);
        System.out.println("删除索引0后: " + list);
        
        // 批量添加
        ArrayList<String> anotherList = new ArrayList<>();
        anotherList.add("Fig");
        anotherList.add("Grape");
        list.addAll(anotherList);
        System.out.println("批量添加后: " + list);
        
        // 批量删除
        list.removeAll(anotherList);
        System.out.println("批量删除后: " + list);
        
        // 清空列表
        list.clear();
        System.out.println("清空后: " + list);
        System.out.println("是否为空: " + list.isEmpty());

2、LinkedList

底层结构:

基于双向链表实现。

核心特点:

内存不连续,节点通过前驱和后继指针相连。在链表任意位置插入或删除元素时,只需修改指针指向(时间复杂度为 O(1)),无需移动元素。但随机访问需要从头或尾遍历,效率较低(时间复杂度为 O(n))。

适用场景:

频繁的首尾操作:虽然它适合中间增删,但在实际开发中,它更多被用来实现栈(Stack)或队列(Queue)。

复杂的增删业务:极少数需要在列表中间频繁进行大量插入、删除操作的特定算法场景。

注意事项:

如果要用到队列和栈,更推荐使用 ArrayDeque(基于数组的双端队列)。它的内存更紧凑,且在首尾操作的性能上通常优于 LinkedList。

示例代码:

java 复制代码
// 创建 LinkedList
        LinkedList<String> list = new LinkedList<>();
        
        // 添加元素(尾部)
        list.add("First");
        list.add("Second");
        list.add("Third");
        list.add("Fourth");
        System.out.println("初始列表: " + list);
        
        // 添加到头部和尾部
        list.addFirst("Head");
        list.addLast("Tail");
        System.out.println("添加头尾后: " + list);
        
        // 使用 offer 方法(队列操作)
        list.offer("Offer1");
        list.offerFirst("OfferFirst");
        list.offerLast("OfferLast");
        System.out.println("offer 操作后: " + list);
        
        // 获取元素(不删除)
        String first = list.getFirst();
        String last = list.getLast();
        System.out.println("第一个元素: " + first);
        System.out.println("最后一个元素: " + last);
        
        // peek 方法(安全获取,空时返回 null)
        String peek = list.peek();
        String peekFirst = list.peekFirst();
        String peekLast = list.peekLast();
        System.out.println("peek: " + peek + ", peekFirst: " + peekFirst + ", peekLast: " + peekLast);
        
        // 修改元素
        list.set(2, "Modified");
        System.out.println("修改后: " + list);
        
        // 获取大小
        System.out.println("列表大小: " + list.size());
        
        // 遍历
        System.out.print("for-each 遍历: ");
        for (String item : list) {
            System.out.print(item + " ");
        }
        System.out.println();
        
        // 栈操作(pop/push)
        String popped = list.pop();
        System.out.println("弹出栈顶: " + popped);
        System.out.println("弹出后: " + list);
        
        list.push("Pushed");
        System.out.println("压入后: " + list);
        
        // 队列操作(poll/remove)
        String polled = list.poll();
        System.out.println("poll 取出: " + polled);
        System.out.println("poll 后: " + list);
        
        String removed = list.removeFirst();
        System.out.println("removeFirst: " + removed);
        System.out.println("removeFirst 后: " + list);
        
        // 查找索引
        int index = list.indexOf("Third");
        System.out.println("Third 的索引: " + index);
        
        // 删除元素
        list.remove("Fourth");
        System.out.println("删除 Fourth 后: " + list);
        
        // 转换为数组
        Object[] array = list.toArray();
        System.out.print("数组内容: ");
        for (Object obj : array) {
            System.out.print(obj + " ");
        }
        System.out.println();
        
        // 清空列表
        list.clear();
        System.out.println("清空后是否为空: " + list.isEmpty());

3、Vector、Stack

底层结构:

与 ArrayList 类似,基于动态数组。

核心特点:

Vector 的所有方法都加了 synchronized 关键字,是线程安全的,但因此带来了极大的性能开销。Stack 继承自 Vector,实现了标准的"后进先出"栈结构。

适用场景:

老旧系统维护:在现代高并发开发中,Vector 和 Stack 已经被淘汰,强烈不推荐在新项目中使用。

替代方案:

如果需要线程安全的 List,推荐使用 CopyOnWriteArrayList;如果需要栈结构,推荐使用 ArrayDeque。

4. CopyOnWriteArrayList

底层结构:

动态数组,采用"写时复制"(Copy-On-Write)机制。

核心特点:

读操作完全无锁,性能极高;写操作(增删改)时会加锁,并复制出一个全新的数组,在新数组上进行修改后再替换原数组。

适用场景:

读多写少需要线程安全场景:如系统中的配置列表等。这些场景下,绝大部分时间都在遍历读取,极少发生修改。

注意事项:

由于每次写操作都要复制整个数组,内存占用和 CPU 开销较大,绝对不能用于写操作频繁的场景。如果需要高频读写,不必须使用List情况下用ConcurrentHashMap或ConcurrentLinkedQueue性能更好。

示例代码:

java 复制代码
 // 创建 CopyOnWriteArrayList
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();

        // 添加元素
        list.add("Item1");
        list.add("Item2");
        list.add("Item3");
        list.add("Item4");
        System.out.println("初始列表: " + list);

        // 在指定位置插入
        list.add(1, "NewItem");
        System.out.println("插入后: " + list);

        // 如果不存在则添加
        boolean added = list.addIfAbsent("Item5");
        System.out.println("添加 Item5: " + added);
        System.out.println("添加后: " + list);

        // 批量添加(如果不存在)
        String[] items = {"Item6", "Item7"};
        int count = list.addAllAbsent(Arrays.asList( items));
        System.out.println("批量添加了 " + count + " 个元素");
        System.out.println("批量添加后: " + list);

        // 获取元素
        String first = list.get(0);
        System.out.println("第一个元素: " + first);

        // 修改元素
        list.set(0, "Modified");
        System.out.println("修改后: " + list);

        // 获取大小
        System.out.println("列表大小: " + list.size());

        // 检查元素
        boolean contains = list.contains("Item2");
        System.out.println("是否包含 Item2: " + contains);

        // 获取快照数组
        Object[] snapshot = list.toArray();
        System.out.print("快照数组: ");
        for (Object obj : snapshot) {
            System.out.print(obj + " ");
        }
        System.out.println();

        // 遍历 - 迭代器(基于快照,线程安全)
        System.out.print("Iterator 遍历: ");
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + " ");
        }
        System.out.println();

        // 遍历 - for-each
        System.out.print("for-each 遍历: ");
        for (String item : list) {
            System.out.print(item + " ");
        }
        System.out.println();

        // 查找索引
        int index = list.indexOf("Item3");
        System.out.println("\nItem3 的索引: " + index);

        // 删除元素
        list.remove("Item2");
        System.out.println("删除 Item2 后: " + list);

        list.remove(0);
        System.out.println("删除索引0后: " + list);

        // 批量删除
        list.removeAll(List.of("Item6", "Item7"));
        System.out.println("批量删除后: " + list);

        // 保留指定元素
        list.retainAll(List.of("Item3", "Item4", "Item5"));
        System.out.println("保留后: " + list);

        // 清空列表
        list.clear();
        System.out.println("清空后是否为空: " + list.isEmpty());

        // 演示线程安全性:遍历时可以安全修改
        System.out.println("\n=== 演示线程安全的遍历 ===");
        CopyOnWriteArrayList<Integer> numbers = new CopyOnWriteArrayList<>();
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);
        numbers.add(4);
        numbers.add(5);

        // 在遍历时添加元素不会抛出 ConcurrentModificationException
        System.out.print("遍历时添加元素: ");
        for (Integer num : numbers) {
            System.out.print(num + " ");
            if (num == 3) {
                numbers.add(6);  // 安全!不会影响当前迭代
            }
        }
        System.out.println();
        System.out.println("遍历完成后: " + numbers);

        // 演示多线程场景
        System.out.println("\n=== 演示多线程读写 ===");
        CopyOnWriteArrayList<String> sharedList = new CopyOnWriteArrayList<>();

        Thread writer1 = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                sharedList.add("Writer1-" + i);
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread writer2 = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                sharedList.add("Writer2-" + i);
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread reader = new Thread(() -> {
            for (int i = 0; i < 3; i++) {
                System.out.println("读取时刻: " + sharedList);
                try {
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        writer1.start();
        writer2.start();
        reader.start();

        try {
            writer1.join();
            writer2.join();
            reader.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("最终列表: " + sharedList);
        System.out.println("列表大小: " + sharedList.size());

二、Set

1、HashSet

底层结构:

基于 HashMap 实现。当你把元素放入 HashSet 时,实际上是作为 HashMap 的 Key 存储的,而 Value 则是一个固定的静态 Object 对象。

核心特点:

去重原理:依赖 hashCode() 和 equals() 方法。如果两个对象的哈希值相同且 equals 为 true,则视为重复元素。

性能:添加、删除、查找的时间复杂度均为 O(1)。

允许空值:允许插入一个 null 元素。

适用场景:

绝大多数不需要顺序、只需要快速去重和查找的场景。

注意事项:

存入自定义对象时,必须重写 hashCode() 和 equals() 方法,否则无法正确去重。

示例代码:

java 复制代码
 // 1. 创建 HashSet
        Set<String> set = new HashSet<>();
        System.out.println("=== 创建 HashSet ===");

        // 2. 添加元素 add()
        System.out.println("\n=== 添加元素 ===");
        set.add("Java");
        set.add("Python");
        set.add("C++");
        set.add("JavaScript");
        set.add("Go");
        System.out.println("HashSet: " + set);

        // 3. 获取大小 size()
        System.out.println("\n=== 获取大小 ===");
        System.out.println("元素个数: " + set.size());

        // 4. 判断是否包含某元素 contains()
        System.out.println("\n=== 判断是否包含 ===");
        System.out.println("是否包含 'Java': " + set.contains("Java"));
        System.out.println("是否包含 'Ruby': " + set.contains("Ruby"));

        // 5. 删除元素 remove()
        System.out.println("\n=== 删除元素 ===");
        set.remove("C++");
        System.out.println("删除 'C++' 后: " + set);
        System.out.println("元素个数: " + set.size());

        // 6. 判断是否为空 isEmpty()
        System.out.println("\n=== 判断是否为空 ===");
        System.out.println("是否为空: " + set.isEmpty());

        // 7. 遍历 HashSet
        System.out.println("\n=== 遍历 HashSet ===");
        
        // 方式1: 增强 for 循环
        System.out.println("方式1 - 增强 for 循环:");
        for (String item : set) {
            System.out.println("  " + item);
        }

        // 方式2: Iterator 迭代器
        System.out.println("\n方式2 - Iterator 迭代器:");
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println("  " + iterator.next());
        }

        // 方式3: forEach + Lambda
        System.out.println("\n方式3 - forEach + Lambda:");
        set.forEach(item -> System.out.println("  " + item));

        // 8. 清空集合 clear()
        System.out.println("\n=== 清空集合 ===");
        set.clear();
        System.out.println("清空后: " + set);
        System.out.println("是否为空: " + set.isEmpty());

        // 9. 批量操作
        System.out.println("\n=== 批量操作 ===");
        Set<String> set1 = new HashSet<>();
        set1.add("A");
        set1.add("B");
        set1.add("C");
        set1.add("D");

        Set<String> set2 = new HashSet<>();
        set2.add("C");
        set2.add("D");
        set2.add("E");
        set2.add("F");

        System.out.println("set1: " + set1);
        System.out.println("set2: " + set2);

        // addAll() - 并集
        Set<String> union = new HashSet<>(set1);
        union.addAll(set2);
        System.out.println("并集 (addAll): " + union);

        // retainAll() - 交集
        Set<String> intersection = new HashSet<>(set1);
        intersection.retainAll(set2);
        System.out.println("交集 (retainAll): " + intersection);

        // removeAll() - 差集
        Set<String> difference = new HashSet<>(set1);
        difference.removeAll(set2);
        System.out.println("差集 (removeAll): " + difference);

        // 10. 转换为数组 toArray()
        System.out.println("\n=== 转换为数组 ===");
        Set<String> set3 = new HashSet<>();
        set3.add("X");
        set3.add("Y");
        set3.add("Z");
        String[] array = set3.toArray(new String[0]);
        System.out.print("数组: ");
        for (String s : array) {
            System.out.print(s + " ");
        }
        System.out.println();

        // 11. HashSet 特性演示:不允许重复元素
        System.out.println("\n=== HashSet 特性:不允许重复 ===");
        Set<Integer> intSet = new HashSet<>();
        intSet.add(1);
        intSet.add(2);
        intSet.add(3);
        intSet.add(2); // 重复元素,不会添加成功
        intSet.add(1); // 重复元素,不会添加成功
        System.out.println("添加重复元素后: " + intSet);
        System.out.println("元素个数: " + intSet.size());

        // 12. HashSet 允许 null 值
        System.out.println("\n=== HashSet 允许 null 值 ===");
        Set<String> nullSet = new HashSet<>();
        nullSet.add("A");
        nullSet.add(null);
        nullSet.add("B");
        System.out.println("包含 null 的 HashSet: " + nullSet);

2、LinkedHashSet

底层结构:

基于 LinkedHashMap 实现。它在 HashMap 的基础上,增加了一条双向链表来维护元素的迭代顺序。

核心特点:

有序性:它保证了插入顺序。遍历时,元素的顺序与插入顺序一致。

性能:由于需要维护链表,性能略低于 HashSet。

适用场景:

需要去重,且希望遍历时保持元素插入顺序的场景。

示例代码(保持插入顺序的去重):

java 复制代码
        LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
        linkedHashSet.add("Java");
        linkedHashSet.add("Python");
        linkedHashSet.add("C++");
        linkedHashSet.add("Java"); // 重复,不会添加
        linkedHashSet.add("JavaScript");
        linkedHashSet.add("Python"); // 重复,不会添加
        System.out.println("结果: " + linkedHashSet);
//结果
结果: [Java, Python, C++, JavaScript]

3、TreeSet

底层结构:

基于 TreeMap 实现,底层数据结构是红黑树。

核心特点:

排序性:元素是自然排序(如数字从小到大,字母 A-Z)或者定制排序(通过 Comparator 接口)。

性能:由于是红黑树结构,添加、删除、查找的时间复杂度为 O(log n)。

不允许空值:插入 null 会抛出 NullPointerException(因为在排序比较时无法处理 null)。

适用场景:

需要对集合中的数据进行排序、范围查找(如查找大于 100 的所有元素)的场景。

示例代码:

java 复制代码
//自定义排序(降序),new TreeSet<>()默认为升序
        TreeSet<Integer> descendingSet = new TreeSet<>(Collections.reverseOrder());
        descendingSet.add(45);
        descendingSet.add(12);
        descendingSet.add(78);
        descendingSet.add(23);
        descendingSet.add(56);
        System.out.println("降序排列: " + descendingSet);
//结果
降序排列: [78, 56, 45, 23, 12]


//自定义对象排序
        TreeSet<Student> students = new TreeSet<>(Comparator.comparingInt(Student::getScore).reversed());
        students.add(new Student("张三", 85));
        students.add(new Student("李四", 92));
        students.add(new Student("王五", 78));
        students.add(new Student("赵六", 95));
        
        System.out.println("按分数降序排列:");
        students.forEach(student -> 
            System.out.println("  " + student.getName() + ": " + student.getScore() + "分")
        );

//结果
按分数降序排列:
  赵六: 95分
  李四: 92分
  张三: 85分
  王五: 78分

4、CopyOnWriteArraySet

底层结构:

内部维护了一个 CopyOnWriteArrayList。每次添加元素都遍历底层数组判断是否重复。

核心特点:

线程安全:它是线程安全的 Set。

写时复制:在执行添加(写)操作时,会复制一个新的数组,在新数组上修改,然后将原数组引用指向新数组。

读操作无锁:读取数据时不需要加锁,性能极高。

适用场景:读多写少的并发场景。

注意事项:

由于写操作涉及数组复制,开销很大,不适合频繁写入的场景;且它只能保证最终一致性,不适合强一致性要求的场景。

三、Queue

1、ArrayDeque

底层结构:

基于可动态扩容的循环数组实现。

核心特点:

它同时实现了 Queue 和 Deque(双端队列)接口。因为没有指针开销且利用了位运算,它的性能通常优于 LinkedList。JDK 官方也推荐使用它来替代过时的 Stack 类作为栈使用。

注意事项:

绝对不允许插入 null 元素,否则会抛出空指针异常。

示例代码(常用方法):

java 复制代码
 // ========== 1. 创建 ArrayDeque ==========
        System.out.println("=== 创建 ArrayDeque ===");
        ArrayDeque<String> deque = new ArrayDeque<>();
        
        // ========== 2. 尾部添加元素(作为队列/栈使用)==========
        System.out.println("\n=== 尾部添加元素 ===");
        deque.addLast("A");
        deque.addLast("B");
        deque.addLast("C");
        deque.offerLast("D");
        deque.offerLast("E");
        System.out.println("当前双端队列: " + deque);
        
        // ========== 3. 头部添加元素 ==========
        System.out.println("\n=== 头部添加元素 ===");
        deque.addFirst("X");
        deque.addFirst("Y");
        deque.offerFirst("Z");
        System.out.println("头部添加后: " + deque);
        
        // ========== 4. 获取大小和判断为空 ==========
        System.out.println("\n=== 基本信息 ===");
        System.out.println("元素个数: " + deque.size());
        System.out.println("是否为空: " + deque.isEmpty());
        
        // ========== 5. 查看首尾元素(不删除)==========
        System.out.println("\n=== 查看首尾元素(不删除)===");
        System.out.println("第一个元素 (getFirst): " + deque.getFirst());
        System.out.println("最后一个元素 (getLast): " + deque.getLast());
        System.out.println("第一个元素 (peekFirst): " + deque.peekFirst());
        System.out.println("最后一个元素 (peekLast): " + deque.peekLast());
        System.out.println("查看后: " + deque);
        
        // ========== 6. 从头部删除元素 ==========
        System.out.println("\n=== 从头部删除元素 ===");
        System.out.println("移除并返回第一个 (removeFirst): " + deque.removeFirst());
        System.out.println("移除并返回第一个 (pollFirst): " + deque.pollFirst());
        System.out.println("当前状态: " + deque);
        
        // ========== 7. 从尾部删除元素 ==========
        System.out.println("\n=== 从尾部删除元素 ===");
        System.out.println("移除并返回最后一个 (removeLast): " + deque.removeLast());
        System.out.println("移除并返回最后一个 (pollLast): " + deque.pollLast());
        System.out.println("当前状态: " + deque);
        // ========== 8. 遍历 ArrayDeque ==========
        System.out.println("\n=== 遍历 ArrayDeque ===");
        System.out.println("方式1 - 增强 for 循环:");
        for (String item : deque) {
            System.out.println("  " + item);
        }
        
        System.out.println("\n方式2 - forEach:");
        deque.forEach(item -> System.out.println("  " + item));
        
        System.out.println("\n方式3 - 迭代器(从头到尾):");
        Iterator<String> iterator = deque.iterator();
        while (iterator.hasNext()) {
            System.out.println("  " + iterator.next());
        }
        
        System.out.println("\n方式4 - 降序迭代器(从尾到头):");
        Iterator<String> descIterator = deque.descendingIterator();
        while (descIterator.hasNext()) {
            System.out.println("  " + descIterator.next());
        }
        

2. LinkedList(既是List,也是Queue)

3、PriorityQueue(优先队列)

底层结构:

基于二叉堆(底层用数组存储)实现。

核心特点:

它不遵循先进先出原则。出队时,会根据元素的自然顺序(默认最小堆)或构造时传入的 Comparator 自定义规则,将优先级最高的元素先出队。

注意事项:

不允许插入 null,且不是线程安全的。如果在多线程环境下需要优先级队列,应使用 PriorityBlockingQueue。

示例代码(自定义排序):

java 复制代码
  //  使用 Lambda 表达式自定义排序(最大堆)
 PriorityQueue<Integer> maxHeap = new PriorityQueue<>(
            (a, b) -> b - a  // 降序排列
        );
        maxHeap.offer(45);
        maxHeap.offer(12);
        maxHeap.offer(78);
        maxHeap.offer(23);
        maxHeap.offer(56);
        
        System.out.print("出队顺序: ");
        while (!maxHeap.isEmpty()) {
            System.out.print(maxHeap.poll() + " ");
        }
//结果
出队顺序: 78 56 45 23 12 





  //使用匿名内部类自定义排序:主要按成绩降序,次要按姓名字典序升序
        PriorityQueue<Student> studentQueue = new PriorityQueue<>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                // 主要条件:按成绩降序(分数高的排前面)
                int scoreCompare = Integer.compare(s2.getScore(), s1.getScore());

                // 次要条件:如果成绩相同,按姓名字典序升序(字母/拼音靠前的排前面)
                if (scoreCompare == 0) {
                    return s1.getName().compareTo(s2.getName());
                }

                return scoreCompare;
            }
        });

        // 添加学生数据
        studentQueue.offer(new Student("张三", 92));
        studentQueue.offer(new Student("李四", 85));
        studentQueue.offer(new Student("王五", 92));
        studentQueue.offer(new Student("赵六", 78));
        studentQueue.offer(new Student("钱七", 85));
        studentQueue.offer(new Student("孙八", 95));
        studentQueue.offer(new Student("周九", 78));

        System.out.println("=== 学生排名(成绩降序,同分按姓名字典序)===");
        int rank = 1;
        while (!studentQueue.isEmpty()) {
            Student student = studentQueue.poll();
            System.out.println("第" + rank++ + "名: " + student.getName() +
                    " - " + student.getScore() + "分");
        }

//结果
=== 学生排名(成绩降序,同分按姓名字典序)===
第1名: 孙八 - 95分
第2名: 张三 - 92分
第3名: 王五 - 92分
第4名: 李四 - 85分
第5名: 钱七 - 85分
第6名: 周九 - 78分
第7名: 赵六 - 78分

4、ConcurrentLinkedQueue(高并发非阻塞)

底层结构:

基于链表的无界队列。

核心特点:

采用 CAS(Compare-And-Swap)无锁算法保证线程安全。由于没有锁的阻塞和上下文切换开销,它在高并发场景下的吞吐量极高。 注意事项:它是非阻塞的,如果队列空了,调用 poll() 会直接返回 null,不会等待。

5、LinkedBlockingQueue(最常用的阻塞队列)

底层结构:

基于链表的可选有界队列。

核心特点:

它是阻塞队列(BlockingQueue 接口的实现)。当队列满时,插入操作会阻塞等待;当队列空时,获取操作会阻塞等待。它使用了两把锁(一把锁头部,一把锁尾部),实现了入队和出队的完全并行,因此在高并发下性能非常出色。

注意事项:

默认容量是 Integer.MAX_VALUE(近似无界)。如果在生产速度远大于消费速度时,极易导致 OOM(内存溢出),建议在创建时手动指定容量。它是 Java 线程池(ThreadPoolExecutor)默认使用的任务队列。

6、ArrayBlockingQueue(固定容量的阻塞队列)

底层结构:

基于数组的有界队列。

核心特点:

必须在创建时指定容量,且容量不可变。它内部只使用了一把锁来保证线程安全。

注意事项:

由于只有一把锁,入队和出队无法并行,在极高并发下性能略逊于 LinkedBlockingQueue。但它的内存占用是固定且可预测的,非常适合用于限流或需要严格控制资源占用的生产者-消费者模型。

7、DelayQueue(延迟队列)

底层结构:

内部基于 PriorityQueue 实现。

核心特点:

放入队列的元素必须实现 Delayed 接口(包含过期时间)。只有当元素的延迟时间到期后,才能通过 take() 或 poll() 方法将其取出。

注意事项:

非常适合处理订单超时自动取消、缓存过期清理等延迟任务场景。


到这里就结束了!

相关推荐
深蓝轨迹1 小时前
RedisTemplate 核心操作API汇总(Spring Data Redis)
java·redis·spring
Cat_Rocky1 小时前
K8s RBAC认证 简单讲
java·docker·kubernetes
一只IT攻城狮1 小时前
️ Spring Boot 文件上传,防御恶意文件攻击
java·spring boot·web安全
多加点辣也没关系1 小时前
数据结构与算法总章
数据结构·算法
ch.ju1 小时前
Java Programming Chapter 3——Subscript of the array
java·开发语言
hnjzsyjyj1 小时前
洛谷 P1305:新二叉树 ← DFS
数据结构·dfs
雨落在了我的手上1 小时前
初识java(三):运算符
java·开发语言
c++之路1 小时前
装饰器模式(Decorator Pattern)
java·开发语言·装饰器模式