ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

05-Java集合框架全景

2026/9/5 9:42:09 拓冰建站 浏览量
05-Java集合框架全景 《Java 面试八股精讲》系列第 5/14 篇。本系列是我对照开源项目 JavaGuidehttps://github.com/Snailclimb/JavaGuide复习时亲手整理的面试笔记力求把高频考点压成“能背、能讲、能画”的密度。如有错漏欢迎评论区指出。List 体系特性ArrayListVectorLinkedList底层结构Object[] 动态数组Object[] 动态数组双向链表线程安全❌✅synchronized❌随机访问⚡ O(1)⚡ O(1) O(n)插入/删除 O(n)尾部 O(1) O(n)⚡ O(1) 仅改指针内存开销较小较小较大节点存 prev/next扩容机制1.5 倍2 倍无需扩容建议✅默认首选❌ 已废弃用 CopyOnWriteArrayList⚠️ 仅频繁头/中部插删时用ArrayList vs 数组ArrayList 动态扩容可trimToSize()收缩数组长度固定ArrayList 支持泛型保证类型安全数组不行ArrayList 只能存对象基本类型用包装类数组可存基本类型ArrayList 有丰富 APIadd/remove数组只能按下标访问ArrayList 创建无需指定大小数组必须指定ArrayList vs LinkedList缓存视角维度ArrayListLinkedList内存布局连续内存块离散节点散落堆中CPU Cache Line✅ 一次加载多元素❌ 节点可能跨缓存行预取机制✅ 可预测预取❌ 无法预测下一节点缓存命中率 极高 频繁 cache miss 实测遍历 100 万元素ArrayList 比 LinkedList 快5~10 倍——差距完全来自缓存而非算法复杂度。ArrayList 扩容机制容量不足时自动扩容为1.5 倍并数组复制迁移。开发中应预分配合理初始容量避免频繁扩容。Set 体系特性HashSetLinkedHashSetTreeSet底层结构HashMapLinkedHashMap红黑树有序性❌ 无序✅ 插入顺序✅ 自然/自定义排序null 值✅ 允许 1 个✅ 允许 1 个❌比较时 NPE时间复杂度O(1)O(1)O(log n)典型场景去重、集合运算保序去重范围查询、排序去重Queue 体系特性PriorityQueueDelayQueueArrayDeque底层结构Object[] 小顶堆PriorityQueue ReentrantLockObject[] 循环数组核心语义最小值优先出队到期才能出队双端高效操作线程安全❌✅阻塞式❌典型场景Top-K、任务调度、Dijkstra定时任务、缓存过期Stack/Queue 最佳替代、滑动窗口三者均不允许 null。BlockingQueueBlockingQueue是生产者-消费者模式的核心基础设施在普通 Queue 上增加线程安全的阻塞能力操作队列为空队列已满取take 阻塞直到有元素—放put— 阻塞直到有空间非阻塞poll/offer返回 null/false返回 false 普通 Queue 是没有就报错BlockingQueue 是没有就等着有了自动唤醒——把同步 等待通知封装进队列无需手写synchronized/wait()/notifyAll()。ArrayBlockingQueue 方法对比新增元素方法队列满时返回值put(e)阻塞直到被唤醒/中断voidoffer(e)返回 falsebooleanoffer(e, timeout, unit)超时阻塞超时返回 falsebooleanadd(e)抛IllegalStateExceptionboolean获取/移除元素方法队列空时返回值take()阻塞直到被唤醒/中断Epoll()返回 nullEpoll(timeout, unit)超时阻塞超时返回 nullEpeek()返回 nullEremove()抛NoSuchElementExceptionbooleanABQ vs LBQ vs CLQ维度ArrayBlockingQueueLinkedBlockingQueueConcurrentLinkedQueue底层结构数组固定容量链表有界/无界链表无界是否阻塞✅✅❌ 非阻塞锁机制单锁 2 Condition双锁takeLockputLock无锁CASvolatile吞吐量中等高生产消费并行极高弱一致性公平性支持公平/非公平仅非公平不适用典型场景有界缓冲、背压控制高吞吐生产消费高频统计、监控收集三个关键差异阻塞 vs 非阻塞ABQ/LBQ 适合流量整形CLQ 适合允许丢失或自行重试的高频轻量场景锁粒度ABQ 单锁互斥是瓶颈LBQ 双锁可并行CLQ 完全无锁但有 ABA 问题和弱一致性有界 vs 无界ABQ 必须有界天然背压防 OOMLBQ 默认无界消费慢易 OOMCLQ 永远无界ArrayBlockingQueue 实现原理内部维护定长数组存储元素ReentrantLock保证读写线程安全两个Condition实现等待/唤醒队列满 → 生产者notFull.await()等待队列空 → 消费者notEmpty.await()等待新增元素 →notEmpty.signal()唤醒消费者取出元素 →notFull.signal()唤醒生产者DelayQueue 核心要点维度核心答案关键细节实现原理PriorityQueue ReentrantLock Condition小顶堆保证延迟最小在堆顶Condition 精准阻塞唤醒避免忙等线程安全✅ReentrantLock 保证原子性使用场景定时任务调度、缓存过期清理到期由消费线程取出执行Delayed 接口定义延迟计算与排序规则getDelay()判断是否到期compareTo()决定堆顺序。两者语义必须一致否则出队错乱vs Timer/TimerTask架构不同DelayQueue 纯数据结构不执行任务Timer 单线程串行长任务阻塞后续。复杂周期调度优先ScheduledThreadPoolExecutorMap 体系特性HashMapTreeMapLinkedHashMapConcurrentHashMap底层结构数组链表/红黑树红黑树哈希表双向链表Node[]链表/红黑树有序性无序Key 排序插入/访问顺序LRU无序null Key/Value1 null Key多 null Value不允许 null Key同 HashMap均不允许线程安全❌❌❌✅ 高并发时间复杂度O(1) 平均O(log n)O(1)O(1) 平均典型用途通用 KV 缓存范围查询、Top-KLRU 缓存高并发计数器HashMap 底层实现JDK 1.8 之前数组 链表链表散列。hashCode经扰动函数处理后用(n-1) hash定位桶位冲突用拉链法解决。扰动函数优化哈希分布、减少碰撞JDK 1.8 之后链表长度 8且数组长度 ≥64时转红黑树数组 64 优先扩容而非转树为什么阈值是 8 和 64泊松分布链表长度达 8 概率小于千万分之一阈值 8 平衡性能与空间小数组扩容成本低优先扩容避免过早引入红黑树数组达 64 冲突概率高红黑树优势显现HashMap 长度为什么是 2 的幂位运算hash (length-1)等价于hash % length比取余高效扩容后元素分布更均匀扩容机制简单只需检查哈希高位——为 0 位置不变为 1 移到原索引 原容量HashMap 多线程死循环问题JDK 1.7 及之前多线程并发扩容时头插法可能形成环形链表导致get死循环、CPU 100%。JDK 1.8 改尾插法避免链表倒置但仍存在数据覆盖问题——并发环境请用ConcurrentHashMap。HashMap 为什么线程不安全数据丢失并发put互相覆盖无限循环仅 JDK 7 及之前头插法扩容成环ConcurrentHashMap 实现JDK 1.8Node CAS synchronized结构与 HashMap 1.8 类似数组链表/红黑树synchronized只锁桶首节点JDK 1.7Segment分段锁继承 ReentrantLock默认 16 段1.7 vs 1.8 差异维度JDK 1.7JDK 1.8线程安全Segment 分段锁CAS synchronized锁粒度更细哈希冲突拉链法拉链法 红黑树并发度受 Segment 数限制默认 16不同桶可并行更新复合操作原子性putIfAbsent、compute、computeIfAbsent、computeIfPresent、merge等均为原子操作可接受函数参数计算并更新 value。《Java 面试八股精讲》系列目录加粗为本篇Java 基础一JDK、JRE、JVM、JIT 与 AOTJava 基础二equals、hashCode 与 StringJava 基础三异常、反射、代理与序列化Java 基础四IO 模型、泛型擦除与值传递5. 集合框架List、Set、Queue、Map 全景本篇JVM一内存区域与对象创建JVM二Class 文件与类加载JVM三垃圾回收算法与收集器Spring一基础与 IoCSpring二Bean 的声明、注入与生命周期Spring三AOP、MVC 与循环依赖Spring四事务详解与失效场景Spring五Spring Boot 与 Web 注解数据库基础与系统设计规范