Java 集合框架

Java 集合框架(Java Collections Framework, JCF)是 Java 开发中最核心、最常用的工具之一,用于高效地存储和操作一组对象。合理选择集合类型对程序的性能、内存占用、线程安全性和代码可读性至关重要。

下面从 分类结构、核心特性、适用场景 三个维度系统介绍 Java 集合,并给出"什么时候用什么集合"的实用建议。


一、Java 集合框架整体结构

复制代码
Collection
├── List(有序、可重复)
│   ├── ArrayList
│   ├── LinkedList
│   └── Vector / Stack(已过时,不推荐)
│
├── Set(无序、不可重复)
│   ├── HashSet
│   ├── LinkedHashSet
│   └── TreeSet
│
└── Queue(队列,FIFO 或优先级)
    ├── LinkedList(也实现 Deque)
    ├── ArrayDeque
    ├── PriorityQueue
    └── BlockingQueue(如 LinkedBlockingQueue)

Map(键值对,非 Collection 子接口)
├── HashMap
├── LinkedHashMap
├── TreeMap
├── Hashtable(过时)
└── ConcurrentHashMap

⚠️ 注意:Map 不属于 Collection 接口体系,但通常被归为集合框架的一部分。


二、各类集合详解与使用场景

1. List ------ 有序、允许重复、按索引访问

实现类 底层结构 查询 插入/删除 线程安全 适用场景
ArrayList 动态数组 O(1)(按索引) O(n)(中间插入/删除) ❌ 否 绝大多数场景首选• 频繁随机访问• 数据量大且读多写少
LinkedList 双向链表 O(n) O(1)(首尾操作) ❌ 否 • 频繁在首尾增删(如栈、队列)• 很少随机访问

📌 建议 :除非明确需要频繁头尾操作,否则优先用 ArrayListLinkedList 内存开销大(每个节点存前后指针),缓存局部性差。


2. Set ------ 无重复元素

实现类 底层 是否有序 是否排序 时间复杂度(add/contains) 适用场景
HashSet HashMap ❌ 无序 O(1) 平均 去重 + 快速查找• 不关心顺序• 如用户ID集合、黑名单
LinkedHashSet LinkedHashMap ✅ 插入顺序 O(1) • 需要保持插入顺序的去重集合• 如记录访问历史
TreeSet TreeMap(红黑树) ✅ 升序(自然 or Comparator) O(log n) • 需要自动排序 • 如排行榜、范围查询(subSet()

📌 关键点

  • HashSet 依赖 hashCode()equals(),务必正确重写!
  • TreeSet 要求元素实现 Comparable 或提供 Comparator

3. Map ------ 键值对存储

实现类 底层 是否有序 是否排序 线程安全 适用场景
HashMap 数组+链表/红黑树(JDK8+) 最常用 Map• 高频 get/put• 如缓存、配置项
LinkedHashMap HashMap + 双向链表 ✅ 插入/访问顺序 • LRU 缓存(重写 removeEldestEntry)• 保持插入或访问顺序
TreeMap 红黑树 ✅ 升序(按 key) • 按 key 范围查询(subMap)• 如按时间戳排序的日志
ConcurrentHashMap 分段锁 / CAS(JDK8+) 高并发场景首选 • 多线程共享 Map• 替代 HashtablesynchronizedMap

📌 注意

  • HashtableCollections.synchronizedMap() 性能差(全表锁),避免使用
  • ConcurrentHashMap 不支持 null key/value。

4. Queue / Deque ------ 队列与双端队列

实现类 特性 适用场景
ArrayDeque 基于循环数组,无界 栈、队列首选 • 替代 StackLinkedList 做队列
LinkedList 双向链表 • 需要同时当 List 和 Queue 用(不推荐混用)
PriorityQueue 二叉堆 • 优先级队列(如任务调度、Top K 问题)
BlockingQueue (如 LinkedBlockingQueue 阻塞队列 • 生产者-消费者模型• 线程池工作队列

📌 建议

  • ArrayDeque 代替 StackStack 继承 Vector,性能差且线程安全冗余)。
  • 高并发生产消费 → 用 BlockingQueue

三、线程安全集合选择

场景 推荐方案
单线程 直接用 ArrayList, HashMap, HashSet
多线程只读 普通集合 + Collections.unmodifiableXxx() 包装
多线程读写(高性能) ConcurrentHashMap, CopyOnWriteArrayList, ConcurrentLinkedQueue
多线程读写(强一致性) Collections.synchronizedXxx()(性能差,慎用)

🔥 重点

  • CopyOnWriteArrayList写时复制 ,适合读多写少(如监听器列表)。
  • ConcurrentHashMap:支持高并发读写,不要用 synchronizedMap

四、快速决策指南(什么时候用什么?)

你的需求 推荐集合
存一组数据,经常通过下标访问 ArrayList
需要去重,不关心顺序 HashSet
需要去重,且保持插入顺序 LinkedHashSet
需要自动排序(如字典序) TreeSetTreeMap
存键值对,高频查询 HashMap
存键值对,需要按插入顺序遍历 LinkedHashMap
多线程共享 Map ConcurrentHashMap
实现栈(LIFO) ArrayDeque(调用 push/pop
实现队列(FIFO) ArrayDeque(调用 offer/poll
任务按优先级处理 PriorityQueue
生产者-消费者模型 BlockingQueue(如 LinkedBlockingQueue

五、最佳实践总结

  1. 默认选择

    • List → ArrayList
    • Set → HashSet
    • Map → HashMap
  2. 需要顺序?

    • 插入顺序 → LinkedHashSet / LinkedHashMap
    • 排序 → TreeSet / TreeMap
  3. 高并发?

    • java.util.concurrent 包下的并发集合,不要自己加 synchronized
  4. 避免过时类

    • 不要用 Vector, Stack, Hashtable
  5. 注意 null 值

    • ConcurrentHashMapTreeMap 等不支持 null key。
  6. 初始化容量

    • 已知数据量大时,构造时指定初始容量(如 new ArrayList(1000)),避免频繁扩容。

结语

Java 集合不是"随便选一个能用就行",而是根据访问模式、数据规模、并发需求、顺序要求 综合权衡的结果。掌握每种集合的内部结构时间复杂度特性,才能写出高性能、可维护的代码。

💡 记住一句话
"读多写少用 CopyOnWrite,高并发用 Concurrent,排序用 Tree,去重用 Hash,顺序用 Linked,队列栈用 ArrayDeque。"

相关推荐
寻寻觅觅☆15 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
l1t16 小时前
在wsl的python 3.14.3容器中使用databend包
开发语言·数据库·python·databend
青云计划16 小时前
知光项目知文发布模块
java·后端·spring·mybatis
赶路人儿16 小时前
Jsoniter(java版本)使用介绍
java·开发语言
ceclar12317 小时前
C++使用format
开发语言·c++·算法
探路者继续奋斗17 小时前
IDD意图驱动开发之意图规格说明书
java·规格说明书·开发规范·意图驱动开发·idd
码说AI17 小时前
python快速绘制走势图对比曲线
开发语言·python
Gofarlic_OMS17 小时前
科学计算领域MATLAB许可证管理工具对比推荐
运维·开发语言·算法·matlab·自动化
星空下的月光影子17 小时前
易语言开发从入门到精通:补充篇·网络爬虫与自动化采集分析系统深度实战·HTTP/HTTPS请求·HTML/JSON解析·反爬策略·电商价格监控·新闻资讯采集
开发语言
老约家的可汗17 小时前
初识C++
开发语言·c++