01-Java 集合框架全景:从 Collection 到 Map 一张关系网理清

两大根接口一张关系网,复杂度速查表存好

很多人学集合框架,是从 List、Map、Set 三个单词开始背的,背完还是串不起来:它们之间到底什么关系?为什么 HashMap 既有"哈希"又有"映射"?Collections 和 Collection 是同一个东西吗?今天我们用一张"关系网"把整个集合框架捋顺,让你之后看任何一篇源码解析都像看地图一样清晰。

一、集合框架为什么要分层?

Java 集合框架(Java Collections Framework,JCF)的设计哲学是:接口定义行为,抽象类提供骨架,具体类给实现。三层各司其职:

  • 接口(Interface) :规定"能做什么",比如 Collection 说"我是一个装元素的容器",List 说"我是有序可重复的",Map 说"我是键值对"。
  • 抽象类(AbstractXxx):实现接口里大部分通用方法,具体类只需补全差异逻辑,避免重复造轮子。
  • 具体类(Concrete) :ArrayList、HashMap、TreeSet 等,提供真正的存储结构和算法。

这种设计让你写业务代码时面向接口编程 :List<User> list = new ArrayList<>(),哪天想换 LinkedList,改一行就行。

二、两大根接口:Collection 与 Map

整个框架有两个互不继承的根,这是初学者最容易迷糊的地方:

复制代码
Collection(单个元素的容器)
├── List(有序、可重复)
│   ├── ArrayList       数组实现,查快改慢
│   ├── LinkedList      双向链表,增删快
│   ├── Vector          线程安全但老旧的数组
│   └── Stack           继承 Vector 的栈(已不推荐)
├── Set(无序、不可重复)
│   ├── HashSet         哈希表,最快
│   ├── LinkedHashSet   哈希 + 双向链表,保插入序
│   └── TreeSet         红黑树,按 key 排序
└── Queue / Deque(队列 / 双端队列)
    ├── ArrayDeque      数组双端队列
    ├── PriorityQueue   堆实现的优先队列
    └── 各阻塞队列(BlockingQueue 家族)

Map(键值对容器,不属于 Collection)
├── HashMap            哈希表,最常用
├── LinkedHashMap      哈希 + 链表,保插入/访问序
├── TreeMap           红黑树,按键排序
├── Hashtable         线程安全但老旧的哈希表
└── ConcurrentHashMap 高并发哈希表

关键点:Map 不是 Collection 的子接口。它的根就是 Map<K,V> 自己。所以 Map 没有 add(),只有 put();它没有继承 Collection 的任何方法。但 Map 提供了 keySet()、values()、entrySet() 三个视图,它们返回的就是 Collection/Set,于是两条线在这里交汇。

一个高频面试题:Collection 和 Collections 的区别?前者是接口(根),后者是一个工具类 ,里面全是静态方法(sort、synchronizedList、emptyList 等),用来操作集合。同理 Arrays 是操作数组的工具类。名字只差一个 s,含义天差地别。

三、List / Set / Queue 的行为契约

面试常让你对比三兄弟,记住它们的"契约"就够了:

接口 元素顺序 重复 索引访问 典型实现
List 有序(插入序) 允许 支持 get(i) ArrayList、LinkedList
Set 无序(HashSet) 禁止 不支持 HashSet、TreeSet
Queue 按排队规则 看实现 一般不支持 ArrayDeque、PriorityQueue

"有序"在 List 里指插入顺序可复现、可用下标访问 ;Set 的 HashSet 不保证顺序,TreeSet 按比较器排但也不是"插入序"。这点极易混淆。

四、时间复杂度速查表(背下来)

这是集合框架最实用的"性能地图",建议存下来:

操作 ArrayList LinkedList HashMap TreeMap HashSet
按索引查 get(i) O(1) O(n) --- --- ---
末尾增 add O(1)* O(1) O(1)* O(log n) O(1)*
中间插/删 O(n) O(1)** --- --- ---
查 contain O(n) O(n) O(1)* O(log n) O(1)*
取最小/最大 O(n) O(n) --- O(log n) ---

* 均摊复杂度,扩容/哈希冲突时退化为更高

** 已知节点引用时 O(1),若要先遍历定位则是 O(n)

一句话总结性能直觉:随机访问多用 ArrayList,头尾增删多用 ArrayDeque/LinkedList,查重/映射多用 HashMap,要排序用 TreeMap/TreeSet。

五、迭代器:统一的遍历方式

不管底层是数组还是链表,Collection 都用同一个 Iterator 遍历:

java 复制代码
List<String> list = new ArrayList<>(List.of("a", "b", "c"));
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    String s = it.next();
    if ("b".equals(s)) it.remove(); // 安全删除
}

注意:遍历时用集合自身的 remove() 会抛 ConcurrentModificationException ,必须用迭代器的 remove(),或用 for-each + 提前收集再删,或用 Iterator。这正是后面调优篇要细讲的 fail-fast 机制。

Map 没有 Iterator,但 entrySet() 返回 Set<Map.Entry<K,V>>,一样能迭代:

java 复制代码
for (Map.Entry<String, Integer> e : map.entrySet()) {
    System.out.println(e.getKey() + "=" + e.getValue());
}

六、Java 8 之后的函数式增强

集合框架在 Java 8 吃到了大红利:

  • Collection.removeIf(Predicate):一行替代"迭代 + 判断 + 删除"。
  • List.replaceAll(UnaryOperator)、sort(Comparator)。
  • Map.forEach、compute、merge、getOrDefault 等,写统计逻辑极爽。
  • Stream API 让集合进入"流水线"时代:list.stream().filter(...).map(...).collect(...)。

例子,按城市统计人数:

java 复制代码
Map<String, Long> cnt = users.stream()
    .collect(Collectors.groupingBy(User::getCity, Collectors.counting()));

但 parallelStream() 不是银弹------共享可变状态、线程不安全集合、小数据量都会让它反而不如串行的,调优篇会专门拆。

七、为什么"面向接口编程"这么重要?

回到开头那句 List<User> list = new ArrayList<>()。当你把方法参数写成 List<T> 而不是 ArrayList<T>,调用方可以传 LinkedList、CopyOnWriteArrayList、Collections.emptyList(),你的方法完全不用改。这是集合框架分层带来的最大红利:解耦"使用方式"和"底层实现"。

同理,返回 Map 的方法,内部想换成 ConcurrentHashMap 提升并发,对外签名不变。写 SDK、写业务分层时,这个习惯能少写无数适配代码。

总结

集合框架 = 两大根(Collection / Map)+ 三层结构(接口 / 抽象类 / 实现)+ 一套统一迭代器。记住"List 有序可重复、Set 不可重复、Map 是键值对且不属于 Collection",再配合复杂度速查表,你就拿到了整个框架的地图。后续源码篇都是在给这张地图填充细节。

相关推荐
xuxigifxfh1 小时前
HJ15 求int型正整数在内存中存储时1的个数
java·开发语言·华为机考
Wokoo71 小时前
自动化测试入门:核心场景、回归测试与 Web 自动化环境搭建
java·开发语言·测试工具
我是人✓2 小时前
Spring IOC注解全解析和Spring整合测试单元
java·后端·spring
智购科技无人售货机工厂店2 小时前
玻璃瓶饮料破损率突然上升,排查发现是取货口缓冲垫老化了~YH
java·开发语言·人工智能·python·eclipse
镜象科技2 小时前
中小学AI心理健康解决方案服务商怎么选?2026年选型参考
android·java·人工智能
阿狗童鞋2 小时前
高并发系统设计实战指南
java·spring boot·spring cloud
Sam_Deep_Thinking2 小时前
CountDownLatch实现原理
java·后端·面试·程序员
小狼Solar2 小时前
SAP MDG 功能范围说明(基于S/4HANA 2025)
java·开发语言
范中勤2 小时前
Python 与 Java:模块、包、对象、反射核心差异总结
java·python·面试·反射·元类