Java集合框架 🔥 结构化
核心定位:Java集合框架是存储/管理/操作一组数据的容器体系,替代原生数组的短板,提供动态扩容、增删改查、排序、筛选等丰富功能,是开发必备、面试高频的核心知识点。
一、集合框架核心概述
✅ 核心定义与优势
集合:Java提供的容器类,用于存储多个对象(基本数据类型会自动装箱为包装类)。
对比数组的核心优势:
✅ 长度动态可变,无需初始化指定长度;
✅ 内置海量API,支持增删改查、排序、去重、遍历等操作;
✅ 支持泛型,编译期校验数据类型,避免类型转换异常;
✅ 体系完善,可根据业务场景(有序/无序、可重复/不可重复、键值对)灵活选型。
✅ 整体体系结构(必背|脑图级清晰)
Java集合框架的顶层分为两大核心接口,所有集合类均基于这两个接口实现,无继承关系。
- 单列集合「Collection」------ 存储单个元素
核心特征:每个位置仅存放一个元素,是最基础的集合类型
Collection 【顶层接口】
├─ List 【子接口】:有序、可重复、有索引,支持按索引操作
│ ├─ ArrayList(数组实现):开发首选、查询快、增删慢
│ ├─ LinkedList(双向链表实现):增删快、查询慢,适配首尾操作场景
│ └─ Vector(数组实现):线程安全、效率极低,几乎弃用
└─ Set 【子接口】:无序、不可重复、无索引,核心作用是去重
├─ HashSet(哈希表实现):去重首选、效率最高,底层依赖HashMap
│ └─ LinkedHashSet:有序HashSet,记录元素插入顺序
└─ TreeSet(红黑树实现):自动排序,需实现Comparable接口
- 双列集合「Map」------ 存储键值对<K,V>
核心特征:以「键(Key)+值(Value)」形式存储,键唯一、值可重复,通过键快速查找值,开发高频使用
Map 【顶层接口】
├─ HashMap(哈希表实现):键值对首选、无序、效率最高、线程不安全
│ └─ LinkedHashMap:有序HashMap,记录键值对插入顺序
├─ TreeMap(红黑树实现):按键自动排序
└─ Hashtable(哈希表实现):线程安全、效率极低,几乎弃用
✅ 核心工具类
java.util.Collections:集合的工具类,提供静态方法实现集合的排序、反转、线程安全包装、查找最值等操作(注意区分:Collection是接口,Collections是工具类)。
二、核心集合类精讲(实战+源码级要点)
✅ 1. ArrayList(List核心|开发使用率95%+)
✔️ 底层实现
JDK全版本基于动态数组实现,默认初始容量10,扩容规则为原容量1.5倍。
✔️ 核心特点
✅ 查询/修改快(数组下标访问,时间复杂度O(1));
✅ 新增/删除慢(需移动数组元素,时间复杂度O(n));
✅ 有序、可重复、有索引;
✅ 非线程安全,效率高。
✔️ 实战代码(高频操作)
import java.util.ArrayList;
import java.util.List;
public class ArrayListDemo {
public static void main(String[] args) {
// 1. 创建对象(泛型限定类型,接口引用指向实现类 → 多态)
List<String> list = new ArrayList<>();
// 2. 核心操作:增、删、改、查
list.add("Java"); // 新增元素
list.add("MySQL");
list.add("Java"); // 允许重复
list.remove(0); // 按索引删除
list.set(0, "Redis");// 按索引修改
String val = list.get(0); // 按索引查询
// 3. 三种遍历方式(开发必会)
// 方式1:增强for(推荐,简洁)
for (String s : list) {
System.out.println(s);
}
}
}
✅ 2. LinkedList(List分支|适配高频增删场景)
✔️ 底层实现
基于双向链表实现,无数组扩容概念,每个节点存储元素+前驱/后继节点地址。
✔️ 核心特点
✅ 新增/删除快(仅需修改节点引用,时间复杂度O(1));
✅ 查询/修改慢(需遍历链表,时间复杂度O(n));
✅ 支持队列/栈的API(addFirst()/addLast()/pop()),适配首尾操作场景;
✅ 非线程安全。
✔️ 核心场景
频繁对集合首尾元素进行增删操作(如消息队列、任务栈)。
✅ 3. HashSet(Set核心|去重首选)
✔️ 底层实现
底层依赖HashMap:将元素作为HashMap的Key,Value固定为一个空对象PRESENT,利用HashMap的键唯一性实现去重。
✔️ 核心特点
✅ 无序、不可重复、无索引;
✅ 去重效率极高,时间复杂度O(1);
✅ 存储自定义对象时,必须重写hashCode()和equals(),否则无法实现去重。
✔️ 实战代码
import java.util.HashSet;
import java.util.Set;
public class HashSetDemo {
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
set.add(1); // 重复元素,自动去重
System.out.println(set); // 输出:[1,2]
}
}
✅ 4. HashMap(Map核心|键值对首选)
✔️ 底层实现(面试必考)
• JDK7:数组 + 链表;
• JDK8及以后:数组 + 链表 + 红黑树(当链表长度≥8、数组容量≥64时,链表转红黑树,查询效率从O(n)→O(logn))。
✔️ 核心特点
✅ 键唯一、值可重复,键为null仅允许1个,值为null无限制;
✅ 无序、非线程安全、效率最高;
✅ 默认初始容量16,负载因子0.75,扩容规则为原容量2倍。
✔️ 实战代码(高频操作)
import java.util.HashMap;
import java.util.Map;
public class HashMapDemo {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
// 增:存键值对
map.put("Java", 90);
map.put("MySQL", 85);
// 查:按键取值
int score = map.get("Java");
// 删:按键删除
map.remove("MySQL");
// 遍历:键值对遍历(推荐)
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println("键:" + entry.getKey() + ",值:" + entry.getValue());
}
}
}
三、高频核心对比(面试必考|易混点梳理)
✅ 1. List vs Set
维度 List Set
有序性 有序(按插入顺序) 无序(HashSet)/有序(LinkedHashSet/TreeSet)
重复性 允许重复 不允许重复
索引 有索引,支持下标操作 无索引,无法通过下标访问
核心方法 get(int index)、set(int index) 无索引相关方法,核心是add()去重
✅ 2. ArrayList vs LinkedList
维度 ArrayList LinkedList
底层结构 动态数组 双向链表
读写效率 查询O(1)、增删O(n) 增删O(1)、查询O(n)
内存占用 连续内存,占用少 节点存储额外引用,占用多
核心场景 查多改少(如数据展示) 增删多查少(如消息队列)
✅ 3. HashMap vs Hashtable
维度 HashMap Hashtable
线程安全 非线程安全,效率高 线程安全,效率极低
空值支持 键允许1个null,值允许多个null 键/值均不允许null
初始容量 16,扩容2倍 11,扩容2n+1
开发选型 开发首选(线程安全场景用ConcurrentHashMap) 完全弃用
✅ 4. HashSet vs TreeSet
维度 HashSet TreeSet
底层实现 哈希表(HashMap) 红黑树
有序性 无序 自动升序排列
去重规则 重写hashCode()+equals() 实现Comparable接口(重写compareTo())
效率 高(O(1)) 较低(O(logn))
四、集合核心考点(源码+面试级)
✅ 1. 泛型(集合标配|必用)
• 语法:ArrayList<String> list,限定集合只能存储指定类型的元素;
• 核心作用:编译期类型校验,避免运行时ClassCastException,无需手动强制类型转换;
• 本质:编译期语法糖,编译后泛型会被擦除,底层仍为Object类型。
✅ 2. HashSet如何保证元素不可重复?(面试高频)
-
当向HashSet添加元素时,先调用元素的hashCode()计算哈希值,确定元素在数组中的存储位置;
-
若该位置无元素,直接存入;若有元素,调用equals()比较两个元素是否相等;
-
✅ equals返回true → 视为重复元素,拒绝添加;
-
✅ equals返回false → 哈希冲突,以链表/红黑树形式挂载在该位置。
结论:存储自定义对象时,必须同时重写hashCode()和equals(),否则无法实现去重。
✅ 3. HashMap的扩容机制(源码级)
-
默认初始容量16,负载因子0.75,阈值=容量×负载因子(默认12);
-
当集合中元素数量≥阈值时,触发扩容,扩容后容量为原容量2倍;
-
扩容时会新建数组,将原数组的元素重新计算哈希值,迁移至新数组(哈希重排)。
✅ 4. 集合的线程安全问题
• 基础集合(ArrayList/HashSet/HashMap)均非线程安全,多线程环境下会出现并发修改异常(ConcurrentModificationException);
• 解决方案:
✅ 方案1:使用Collections.synchronizedXXX()工具类包装(如Collections.synchronizedList(new ArrayList<>()));
✅ 方案2:使用JUC并发集合(如CopyOnWriteArrayList、ConcurrentHashMap),效率更高,开发首选。
✅ 5. 集合遍历方式(开发必会)
✔️ 单列集合遍历(List/Set)
-
增强for循环(推荐,简洁);
-
迭代器Iterator(支持遍历中删除元素,避免并发修改异常);
-
List专属:普通for循环(按索引遍历)。
✔️ 双列集合遍历(Map)
-
键值对遍历entrySet()(推荐,效率最高);
-
按键遍历keySet() + get(key)(效率低,二次查询);
-
按值遍历values()(仅需获取值时使用)。
五、高频面试题汇总(分基础/进阶)
✅ 基础必问(入行级)
-
Java集合框架的两大顶层接口是什么?各自的特点?
-
ArrayList和LinkedList的区别及使用场景?
-
HashSet和TreeSet的区别?HashSet如何保证元素不可重复?
-
HashMap的键和值有什么限制?
-
Collection和Collections的区别?
✅ 进阶常考(面试级)
-
HashMap的底层实现?JDK8做了哪些优化?
-
HashMap的哈希冲突如何解决?为什么链表转红黑树的阈值是8?
-
为什么HashMap的初始容量是16,且必须是2的幂次?
-
集合遍历中出现ConcurrentModificationException的原因及解决方案?
-
如何实现集合的排序?(List用Collections.sort()、TreeSet/TreeMap实现Comparable接口)
六、核心总结(速记|考点提炼)
-
集合框架分为Collection(单列) 和Map(双列) 两大体系,核心是「接口+实现类」的多态设计;
-
ArrayList 是开发首选集合,HashMap 是开发首选键值对容器,HashSet 是去重首选;
-
集合的核心痛点:泛型限定类型、去重规则、线程安全、遍历方式;
-
集合的设计思想完美体现Java面向对象的封装、多态,是OOP思想的落地典范。