Java 集合框架入门:List、Set、Queue 与 Map

文章目录

    • 前言
    • 一、为什么需要集合框架
      • [1.1 数组的局限](#1.1 数组的局限)
      • [1.2 集合框架解决了什么问题](#1.2 集合框架解决了什么问题)
    • [二、Java 集合框架的整体结构](#二、Java 集合框架的整体结构)
      • [2.1 两条核心支线](#2.1 两条核心支线)
      • [2.2 接口与实现类](#2.2 接口与实现类)
    • 三、List:有序、可重复的列表
      • [3.1 List 的特点](#3.1 List 的特点)
      • [3.2 ArrayList:动态数组](#3.2 ArrayList:动态数组)
      • [3.3 LinkedList:双向链表](#3.3 LinkedList:双向链表)
    • 四、Set:元素不能重复的集合
      • [4.1 Set 的特点](#4.1 Set 的特点)
      • [4.2 HashSet:快速去重](#4.2 HashSet:快速去重)
      • [4.3 LinkedHashSet:去重并保留原顺序](#4.3 LinkedHashSet:去重并保留原顺序)
      • [4.4 TreeSet:去重并排序](#4.4 TreeSet:去重并排序)
    • [五、Queue 与 Deque:等待处理的数据队列](#五、Queue 与 Deque:等待处理的数据队列)
      • [5.1 Queue:先进先出的排队结构](#5.1 Queue:先进先出的排队结构)
      • [5.2 Deque:两端都能操作的队列](#5.2 Deque:两端都能操作的队列)
      • [5.3 PriorityQueue:优先处理重要任务](#5.3 PriorityQueue:优先处理重要任务)
    • 六、Map:通过键查找值
      • [6.1 Map 的特点](#6.1 Map 的特点)
      • [6.2 HashMap:最常用的键值容器](#6.2 HashMap:最常用的键值容器)
      • [6.3 LinkedHashMap:按插入顺序遍历](#6.3 LinkedHashMap:按插入顺序遍历)
      • [6.4 TreeMap:按照键排序](#6.4 TreeMap:按照键排序)
    • 七、常用集合如何选择
      • [7.1 选型思路](#7.1 选型思路)
      • [7.2 最常见的默认选择](#7.2 最常见的默认选择)
    • 八、测试代码
    • 九、常见易混知识点
      • [9.1 Collection 与 Collections 不一样](#9.1 Collection 与 Collections 不一样)
      • [9.2 Map 不属于 Collection 子接口](#9.2 Map 不属于 Collection 子接口)
    • 总结

前言

在程序开发中,我们经常需要保存和处理一组数据,例如购物车中的商品、文章标签、排队等待执行的任务、学生姓名与成绩的对应关系。

数组虽然也能保存多个元素,但它的长度固定,增删元素不够灵活。Java 集合框架就像一套准备好的"数据收纳工具箱":不同的容器有不同的摆放规则,也适用于不同的业务场景。

Java 集合框架主要分为两条路线:

  • Collection:保存一个个独立元素,下面包括 ListSetQueue
  • Map:保存键值对,例如"用户名 → 用户信息"。

需要特别注意:Map 属于集合框架的一部分,但它不是 Collection 的子接口。


一、为什么需要集合框架

1.1 数组的局限

数组适合保存数量比较固定的数据:

java 复制代码
String[] names = new String[3];
names[0] = "张三";
names[1] = "李四";
names[2] = "王五";

但是,当数据数量不断变化时,数组会显得不够灵活:

  • 数组长度创建后不能自动改变。
  • 中间插入或删除元素比较麻烦。
  • 查找、去重、排序等操作通常需要自己编写代码。

例如,一个购物车可能随时添加或删除商品;一个班级的签到名单也可能不断变化。这时,集合比数组更适合。

1.2 集合框架解决了什么问题

Java 集合框架提供了统一的接口和常用实现类,使我们可以直接完成以下操作:

java 复制代码
list.add("Java");
list.remove("MySQL");
set.contains("Redis");
map.get("张三");
queue.poll();

可以把集合框架理解为不同用途的容器:

容器 形象理解 典型用途
List 可重复的排号座位表 购物车、学生名单
Set 不允许重复入场的名单 标签去重、用户名检测
Queue 排队窗口 打印任务、消息处理
Deque 两头都能进出的通道 栈、撤销操作
Map 按编号查资料的柜子 用户 ID 查询、配置表

二、Java 集合框架的整体结构

2.1 两条核心支线

Java 集合框架的基础结构可以简化为:

text 复制代码
Iterable
   |
Collection
   ├── List
   │     ├── ArrayList
   │     └── LinkedList
   │
   ├── Set
   │     ├── HashSet
   │     ├── LinkedHashSet
   │     └── TreeSet
   │
   └── Queue
         ├── PriorityQueue
         └── Deque
               ├── ArrayDeque
               └── LinkedList

Map
   ├── HashMap
   ├── LinkedHashMap
   └── TreeMap

其中:

  • List 关注元素的排列位置。
  • Set 关注元素不能重复。
  • Queue 关注元素按照某种规则依次处理。
  • Map 关注通过唯一的键查找对应的值。(二哥的Java进阶之路)

2.2 接口与实现类

实际开发中,通常使用接口声明变量,再选择具体实现类创建对象:

java 复制代码
List<String> list = new ArrayList<>();
Set<String> set = new HashSet<>();
Queue<String> queue = new ArrayDeque<>();
Map<String, Integer> map = new HashMap<>();

这种写法可以理解为:

  1. 左边决定"我需要什么功能"
  2. 右边决定"底层使用什么结构实现"

例如:

java 复制代码
List<String> list = new ArrayList<>();

表示当前业务需要的是"列表"功能,至于底层先使用动态数组实现。以后需要更换实现类时,业务代码受到的影响会更小。


三、List:有序、可重复的列表

3.1 List 的特点

List 表示一个有顺序的集合,元素可以重复,并且可以通过下标访问。

java 复制代码
List<String> courses = new ArrayList<>();

courses.add("Java");
courses.add("MySQL");
courses.add("Java");

System.out.println(courses);        // [Java, MySQL, Java]
System.out.println(courses.get(1)); // MySQL

这里第二次添加 "Java" 不会被拦截,因为 List 允许重复元素。

适用场景:

  • 购物车商品列表。
  • 用户浏览记录。
  • 按顺序展示的文章评论。
  • 考试成绩列表。

List 官方定义强调了两个核心能力:元素具有顺序,并且可以按整数下标访问;它通常允许重复元素。(Oracle Docs)

3.2 ArrayList:动态数组

ArrayList 底层可以理解为一个能够自动扩容的数组。

java 复制代码
List<String> cart = new ArrayList<>();

cart.add("键盘");
cart.add("鼠标");
cart.add("显示器");

System.out.println(cart.get(1)); // 鼠标

它的特点如下:

操作 特点
按下标查询 快,适合频繁读取
尾部添加元素 通常较快
中间插入或删除 需要移动后面的元素
内存结构 元素连续存放,额外开销较少

可以把 ArrayList 想象成一排电影院座位。找到第 10 个座位很快,但如果要在中间增加一个座位,后面的人可能都要往后移动。

适用场景:

  • 查询操作多的列表。
  • 商品展示列表。
  • 查询结果集合。
  • 一般业务中的默认 List 实现。

ArrayListList 的可调整大小数组实现,并实现了随机访问能力。(Oracle Docs)

3.3 LinkedList:双向链表

LinkedList 底层由一个个相互连接的节点组成,每个节点知道前一个节点和后一个节点。

java 复制代码
List<String> history = new LinkedList<>();

history.add("首页");
history.add("课程页");
history.add("订单页");

System.out.println(history);

它的特点如下:

操作 特点
按下标查询 需要沿节点寻找,效率较低
首尾添加、删除 比较适合
中间插入、删除 找到位置后修改连接关系较方便
内存结构 每个节点需要保存前后引用

可以把 LinkedList 想象成一列手拉手的小火车。增加或移除一节车厢时,只需要调整相邻连接;但要直接找到第 100 节车厢,就需要一路数过去。

需要注意:不能简单理解为"LinkedList 任意位置增删都一定快"。如果需要先通过下标找到中间位置,寻找节点本身仍然需要遍历。

LinkedList 同时实现了 ListDeque,按下标访问时会从头部或尾部开始遍历。(Oracle Docs)


四、Set:元素不能重复的集合

4.1 Set 的特点

Set 的核心特点是:不允许保存重复元素

java 复制代码
Set<String> tags = new HashSet<>();

tags.add("Java");
tags.add("MySQL");
tags.add("Java");

System.out.println(tags.size()); // 2

第二次添加 "Java" 时,集合不会重复保存它。

适用场景:

  • 对文章标签去重。
  • 判断用户名是否已经存在。
  • 统计不重复的访问用户。
  • 保存不能重复的编号。

需要特别注意:

Set 的核心定义是"不重复",而不是"所有实现类都无序"。

不同实现类对顺序的处理方式不同:

实现类 是否去重 顺序特点
HashSet 不保证遍历顺序
LinkedHashSet 保留插入顺序
TreeSet 按自然顺序或比较器排序

Set 接口规定元素不能重复;HashSet 不保证遍历顺序,而 LinkedHashSetTreeSet 分别提供插入顺序和排序能力。(Oracle Docs)

4.2 HashSet:快速去重

HashSet 底层基于 HashMap 实现,适合快速判断某个元素是否存在。

java 复制代码
Set<String> uniqueTags = new HashSet<>();

uniqueTags.add("Java");
uniqueTags.add("Redis");
uniqueTags.add("Java");

System.out.println(uniqueTags.contains("Redis")); // true
System.out.println(uniqueTags.size());            // 2

适用场景:

  • 单词去重。
  • 用户 ID 去重。
  • 快速判断数据是否已经处理过。
java 复制代码
List<String> words = Arrays.asList("Java", "MySQL", "Java", "Redis");
Set<String> uniqueWords = new HashSet<>(words);

System.out.println(uniqueWords);

当哈希分布良好时,HashSetaddremovecontainssize 等基本操作通常具有常数时间性能。(Oracle Docs)

4.3 LinkedHashSet:去重并保留原顺序

如果既想去重,又想保留元素首次出现的顺序,可以使用 LinkedHashSet

java 复制代码
Set<String> tags = new LinkedHashSet<>();

tags.add("Java");
tags.add("MySQL");
tags.add("Java");
tags.add("Redis");

System.out.println(tags); // [Java, MySQL, Redis]

适用场景:

  • 对用户提交的数据去重,但保持展示顺序。
  • 对搜索关键词去重,同时保留原始输入顺序。

4.4 TreeSet:去重并排序

TreeSet 会在去重的同时,对元素进行排序。

java 复制代码
Set<Integer> scores = new TreeSet<>();

scores.add(90);
scores.add(75);
scores.add(88);
scores.add(75);

System.out.println(scores); // [75, 88, 90]

适用场景:

  • 保存不重复且需要排序的分数。
  • 保存有序编号。
  • 查询某个范围内的数据。

TreeSet 基于 TreeMap,按照元素的自然顺序或指定比较器进行排序,其基础操作具有 O(log n) 的时间成本。(Oracle Docs)


五、Queue 与 Deque:等待处理的数据队列

5.1 Queue:先进先出的排队结构

Queue 表示队列,通常遵循先进先出原则,即先来的元素先处理。

java 复制代码
Queue<String> printQueue = new ArrayDeque<>();

printQueue.offer("文档A");
printQueue.offer("文档B");
printQueue.offer("文档C");

System.out.println(printQueue.poll()); // 文档A
System.out.println(printQueue.poll()); // 文档B

可以把队列理解为食堂排队:

text 复制代码
入队:新同学站到队尾
出队:最前面的同学先打饭离开

适用场景:

  • 打印任务队列。
  • 消息消费队列。
  • 请求排队处理。
  • 广度优先搜索。

Queue 常用方法有两组:

操作 失败时抛异常 失败时返回特殊值
插入元素 add(e) offer(e)
删除队首 remove() poll()
查看队首 element() peek()

日常使用中,offer()poll()peek() 往往更安全,因为队列为空时不会直接抛出异常。Queue 通常采用先进先出规则,但 PriorityQueue 等实现类可以使用不同的出队规则。(Oracle Docs)

5.2 Deque:两端都能操作的队列

Deque 是双端队列,元素可以从头部加入或删除,也可以从尾部加入或删除。

java 复制代码
Deque<String> deque = new ArrayDeque<>();

deque.addFirst("B");
deque.addFirst("A");
deque.addLast("C");

System.out.println(deque); // [A, B, C]

Deque 既可以模拟普通队列,也可以模拟栈。

作为队列使用
java 复制代码
Queue<String> queue = new ArrayDeque<>();

queue.offer("任务A");
queue.offer("任务B");

System.out.println(queue.poll()); // 任务A
作为栈使用
java 复制代码
Deque<String> stack = new ArrayDeque<>();

stack.push("首页");
stack.push("商品页");
stack.push("订单页");

System.out.println(stack.pop()); // 订单页
System.out.println(stack.pop()); // 商品页

适用场景:

  • 浏览器返回记录。
  • 编辑器撤销功能。
  • 深度优先搜索。
  • 普通业务队列。

虽然 ArrayDeque 底层使用数组实现,但它不是 List,不能通过 get(0) 这样的下标方式访问元素。官方文档还指出,ArrayDeque 用作栈时通常比 Stack 更快,用作队列时通常比 LinkedList 更快。(Oracle Docs)

5.3 PriorityQueue:优先处理重要任务

普通队列按照先来后到处理任务,而 PriorityQueue 会按照优先级决定谁先出队。

java 复制代码
Queue<Integer> queue = new PriorityQueue<>();

queue.offer(80);
queue.offer(100);
queue.offer(60);

System.out.println(queue.poll()); // 60

默认情况下,数字越小,越先出队。

如果希望"优先级数字越大,任务越重要",可以提供比较器:

java 复制代码
Queue<Integer> queue = new PriorityQueue<>(Comparator.reverseOrder());

queue.offer(80);
queue.offer(100);
queue.offer(60);

System.out.println(queue.poll()); // 100

适用场景:

  • 线上故障优先处理。
  • 医院急诊排队。
  • 考试成绩排名处理。
  • 定时任务调度。

需要注意:PriorityQueue 只保证每次 poll() 取出的元素符合优先级规则,直接遍历整个队列时,不保证输出结果已经完全排好序。(Oracle Docs)


六、Map:通过键查找值

6.1 Map 的特点

Map 保存的是键值对:

text 复制代码
键 key  →  值 value

例如:

text 复制代码
学号       → 学生姓名
商品编号   → 商品详情
用户名     → 登录信息
配置名称   → 配置值

示例:

java 复制代码
Map<String, Integer> scores = new HashMap<>();

scores.put("张三", 90);
scores.put("李四", 86);

System.out.println(scores.get("张三")); // 90

Map 中的键不能重复。相同的键再次调用 put() 时,新值会替换旧值:

java 复制代码
scores.put("张三", 95);

System.out.println(scores.get("张三")); // 95

可以把 Map 理解为快递柜:

text 复制代码
柜门编号是 key
柜门里面的包裹是 value
同一个柜门编号只能对应一个当前位置上的包裹

Map 的官方定义是键到值的映射,一个键最多只能映射到一个值。(Oracle Docs)

6.2 HashMap:最常用的键值容器

HashMap 是日常开发中非常常见的 Map 实现。

java 复制代码
Map<String, String> users = new HashMap<>();

users.put("1001", "张三");
users.put("1002", "李四");

System.out.println(users.get("1001")); // 张三

适用场景:

  • 用户 ID 查询用户信息。
  • 商品编号查询商品详情。
  • 单词出现次数统计。
  • 缓存临时数据。
java 复制代码
Map<String, Integer> wordCount = new HashMap<>();

wordCount.put("Java", 1);
wordCount.put("MySQL", 1);
wordCount.put("Java", wordCount.get("Java") + 1);

System.out.println(wordCount.get("Java")); // 2

HashMap 不保证遍历顺序;当哈希分布良好时,其 get()put() 等基本操作通常具有常数时间性能。(Oracle Docs)

6.3 LinkedHashMap:按插入顺序遍历

如果希望键值对按照加入顺序输出,可以使用 LinkedHashMap

java 复制代码
Map<String, Integer> steps = new LinkedHashMap<>();

steps.put("登录", 1);
steps.put("选择商品", 2);
steps.put("提交订单", 3);

System.out.println(steps.keySet()); // [登录, 选择商品, 提交订单]

适用场景:

  • 需要固定展示顺序的配置项。
  • 需要记录访问顺序的数据。
  • 需要实现简单 LRU 缓存的场景。

LinkedHashMap 在哈希表基础上维护了链表,因此拥有明确的遍历顺序,默认通常是插入顺序。(Oracle Docs)

6.4 TreeMap:按照键排序

TreeMap 会按照键的自然顺序或比较器规则进行排序。

java 复制代码
Map<Integer, String> ranking = new TreeMap<>();

ranking.put(3, "铜牌");
ranking.put(1, "金牌");
ranking.put(2, "银牌");

System.out.println(ranking); // {1=金牌, 2=银牌, 3=铜牌}

适用场景:

  • 按编号排序的数据。
  • 按日期排序的记录。
  • 需要范围查询的数据。

TreeMap 基于红黑树实现,其 put()get()remove()containsKey() 等操作具有 O(log n) 的时间成本。(Oracle Docs)


七、常用集合如何选择

7.1 选型思路

选择集合时,不要先背实现类,而应该先问业务需要什么能力:

业务需求 推荐接口 常用实现类
数据允许重复,并且需要下标访问 List ArrayList
数据允许重复,经常在首尾操作 List / Deque LinkedListArrayDeque
数据不能重复,不关心顺序 Set HashSet
数据不能重复,同时保留插入顺序 Set LinkedHashSet
数据不能重复,同时自动排序 Set TreeSet
按先来后到处理任务 Queue ArrayDeque
按优先级处理任务 Queue PriorityQueue
根据唯一键快速查询值 Map HashMap
根据键查询值,并保留插入顺序 Map LinkedHashMap
根据键查询值,并按键排序 Map TreeMap

7.2 最常见的默认选择

在普通业务开发中,可以先记住以下组合:

java 复制代码
List<String> list = new ArrayList<>();
Set<String> set = new HashSet<>();
Queue<String> queue = new ArrayDeque<>();
Map<String, String> map = new HashMap<>();

当业务明确提出"需要保持顺序""需要自动排序""需要优先级处理"等要求时,再更换为对应实现类。


八、测试代码

下面的完整代码演示以下内容:

  • ArrayList 的增删改查与重复元素。
  • LinkedList 作为普通列表使用。
  • HashSetLinkedHashSetTreeSet 的区别。
  • ArrayDeque 作为队列和栈使用。
  • PriorityQueue 按任务优先级出队。
  • HashMapLinkedHashMapTreeMap 的区别。

代码兼容 JDK 8 及以上版本

java 复制代码
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

/**
 * Java 集合框架综合测试:JDK 8+ 可运行。
 */
public class CollectionFrameworkDemo {

    public static void main(String[] args) {
        testList();
        testSet();
        testQueueAndDeque();
        testPriorityQueue();
        testMap();
    }

    /**
     * 测试 List:
     * 1. 元素有顺序
     * 2. 元素可以重复
     * 3. 可以通过下标访问和修改元素
     */
    private static void testList() {
        System.out.println("===== 1. List:有序、可重复、可按下标访问 =====");

        List<String> shoppingCart = new ArrayList<>();

        shoppingCart.add("Java书");
        shoppingCart.add("键盘");
        shoppingCart.add("Java书");       // List 允许重复
        shoppingCart.add(1, "鼠标");      // 在指定下标插入

        System.out.println("ArrayList 初始内容:" + shoppingCart);
        System.out.println("下标为 1 的商品:" + shoppingCart.get(1));

        shoppingCart.set(1, "无线鼠标");  // 修改指定下标元素
        shoppingCart.remove("键盘");      // 删除指定元素

        System.out.println("修改和删除后:" + shoppingCart);

        List<String> recentPages = new LinkedList<>();
        recentPages.add("首页");
        recentPages.add("课程页");
        recentPages.add("订单页");

        System.out.println("LinkedList 作为普通列表:" + recentPages);
        System.out.println();
    }

    /**
     * 测试 Set:
     * 1. 自动去重
     * 2. 不同实现类具有不同的顺序特点
     */
    private static void testSet() {
        System.out.println("===== 2. Set:元素不重复,具体实现决定顺序 =====");

        List<String> tags = Arrays.asList(
                "Java", "MySQL", "Java", "Redis", "MySQL"
        );

        Set<String> hashSet = new HashSet<>(tags);
        System.out.println("HashSet 去重结果(顺序不保证):" + hashSet);

        Set<String> linkedHashSet = new LinkedHashSet<>(tags);
        System.out.println("LinkedHashSet 去重并保留插入顺序:" + linkedHashSet);

        Set<String> treeSet = new TreeSet<>(tags);
        System.out.println("TreeSet 去重并按自然顺序排序:" + treeSet);

        System.out.println();
    }

    /**
     * 测试 Queue 和 Deque:
     * 1. Queue 按先进先出处理元素
     * 2. Deque 可以作为栈使用
     */
    private static void testQueueAndDeque() {
        System.out.println("===== 3. Queue / Deque:排队处理与栈操作 =====");

        Queue<String> printQueue = new ArrayDeque<>();

        printQueue.offer("文档A");
        printQueue.offer("文档B");
        printQueue.offer("文档C");

        System.out.println("队首但不移除 peek():" + printQueue.peek());

        while (!printQueue.isEmpty()) {
            System.out.println("打印完成:" + printQueue.poll());
        }

        System.out.println("空队列 poll() 返回:" + printQueue.poll());

        Deque<String> browserBackStack = new ArrayDeque<>();

        browserBackStack.push("首页");
        browserBackStack.push("集合框架文章");
        browserBackStack.push("ArrayList 文章");

        System.out.println("当前页面 peek():" + browserBackStack.peek());
        System.out.println("返回上一页,弹出:" + browserBackStack.pop());
        System.out.println("返回后所在页面:" + browserBackStack.peek());

        System.out.println();
    }

    /**
     * 测试 PriorityQueue:
     * 数值越大的任务,优先级越高,越先处理。
     */
    private static void testPriorityQueue() {
        System.out.println("===== 4. PriorityQueue:按优先级处理任务 =====");

        Queue<Task> tasks = new PriorityQueue<>(
                Comparator.comparingInt(Task::getPriority).reversed()
        );

        tasks.offer(new Task("修复线上故障", 100));
        tasks.offer(new Task("回复普通邮件", 10));
        tasks.offer(new Task("发布版本", 80));

        while (!tasks.isEmpty()) {
            System.out.println("处理任务:" + tasks.poll());
        }

        System.out.println();
    }

    /**
     * 测试 Map:
     * 1. key 不能重复
     * 2. 相同 key 再次 put 会覆盖旧 value
     * 3. 不同 Map 实现类的顺序特点不同
     */
    private static void testMap() {
        System.out.println("===== 5. Map:通过唯一键查找值 =====");

        Map<String, Integer> scoreMap = new HashMap<>();

        scoreMap.put("张三", 90);
        scoreMap.put("李四", 86);
        scoreMap.put("张三", 95); // 相同 key 会替换旧 value

        System.out.println("张三最新成绩:" + scoreMap.get("张三"));
        System.out.println("王五成绩,不存在时给默认值:"
                + scoreMap.getOrDefault("王五", 0));

        for (Map.Entry<String, Integer> entry : scoreMap.entrySet()) {
            System.out.println(
                    "学生=" + entry.getKey()
                            + ",成绩=" + entry.getValue()
            );
        }

        Map<String, Integer> insertionOrdered = new LinkedHashMap<>();

        insertionOrdered.put("first", 1);
        insertionOrdered.put("second", 2);
        insertionOrdered.put("third", 3);

        System.out.println("LinkedHashMap 插入顺序:"
                + insertionOrdered.keySet());

        Map<Integer, String> ranking = new TreeMap<>();

        ranking.put(3, "铜牌");
        ranking.put(1, "金牌");
        ranking.put(2, "银牌");

        System.out.println("TreeMap 按 key 排序:" + ranking);
    }

    /**
     * 模拟一个待处理任务。
     */
    private static class Task {
        private final String name;
        private final int priority;

        private Task(String name, int priority) {
            this.name = name;
            this.priority = priority;
        }

        private int getPriority() {
            return priority;
        }

        @Override
        public String toString() {
            return name + "(优先级=" + priority + ")";
        }
    }
}

运行后可以观察到:

text 复制代码
List 中可以同时保存两个"Java书"
Set 会自动去除重复标签
Queue 会按照 文档A → 文档B → 文档C 的顺序处理
Deque 作为栈时,最后访问的页面最先弹出
PriorityQueue 会先处理"修复线上故障"
Map 中张三的成绩会从 90 被更新为 95
LinkedHashMap 会保持 first、second、third 的插入顺序
TreeMap 会按照 1、2、3 的键顺序输出

需要注意:

text 复制代码
HashSet 和 HashMap 的遍历输出顺序不固定,
不要在代码中依赖它们的打印顺序。

九、常见易混知识点

9.1 Collection 与 Collections 不一样

Collection 是集合接口体系的根接口之一:

java 复制代码
Collection<String> collection;

Collections 是工具类,提供排序、反转、查找最大值等静态方法:

java 复制代码
Collections.sort(list);
Collections.reverse(list);
Collections.max(list);

可以简单记忆为:

text 复制代码
Collection  是容器体系
Collections 是操作容器的工具箱

9.2 Map 不属于 Collection 子接口

虽然 Map 也属于 Java 集合框架,但它保存的是键值对,而 Collection 保存的是单个元素。

java 复制代码
List<String> list = new ArrayList<>();
Map<String, Integer> map = new HashMap<>();

它们属于两条不同的体系。


总结

Java 集合框架的核心不是记住大量类名,而是理解不同容器解决的问题:

  • List:保存有顺序、允许重复的数据。
  • Set:保存不能重复的数据。
  • Queue:保存等待处理的数据。
  • Deque:支持两端操作,也可以模拟栈。
  • Map:通过唯一键快速查找对应值。

在常见业务开发中,可以优先掌握:

java 复制代码
ArrayList
HashSet
ArrayDeque
HashMap

当业务进一步要求保持插入顺序、自动排序或优先级处理时,再选择:

java 复制代码
LinkedHashSet
TreeSet
PriorityQueue
LinkedHashMap
TreeMap

理解"需要什么能力,再选择什么容器",比单纯背诵集合类更加重要。

相关推荐
Java 码思客10 小时前
【Spring AI实战】第2章 大模型基础调用:同步/异步/流式输出
java·人工智能·spring·ai
郝学胜-神的一滴10 小时前
系统设计 013:高并发系统缓存:从原理到实践全解析
java·开发语言·python·缓存·系统架构·php·软件构建
欧米欧10 小时前
C++进阶之AVL树
java·服务器·c++
学困昇10 小时前
Linux 信号机制详解:从 Ctrl+C 到 SIGCHLD,一文理解进程信号
linux·c语言·开发语言·人工智能·面试
我是一只码蚁10 小时前
记一次苍穹外卖项目 Maven 编译报错的排查与解决全过程
java·经验分享·笔记·后端·架构·maven
i220818 Faiz Ul10 小时前
理财系统|基于java+vue的家庭理财系统小程序(源码+数据库+文档)
java·vue.js·spring boot·小程序·论文·毕设·理财系统
Mahir0810 小时前
MyBatis 分页与插件深度解密:从插件机制到三大分页方案原理全解
java·后端·mybatis·mybatis-plus·大厂面试题
rayyy910 小时前
卡牌抽取游戏
开发语言·python
阿里嘎多学长10 小时前
2026-05-28 GitHub 热点项目精选
开发语言·程序员·github·代码托管