
两大根接口一张关系网复杂度速查表存好很多人学集合框架是从List、Map、Set三个单词开始背的背完还是串不起来它们之间到底什么关系为什么HashMap既有哈希又有映射Collections和Collection是同一个东西吗今天我们用一张关系网把整个集合框架捋顺让你之后看任何一篇源码解析都像看地图一样清晰。一、集合框架为什么要分层Java 集合框架Java Collections FrameworkJCF的设计哲学是接口定义行为抽象类提供骨架具体类给实现。三层各司其职接口Interface规定能做什么比如Collection说我是一个装元素的容器List说我是有序可重复的Map说我是键值对。抽象类AbstractXxx实现接口里大部分通用方法具体类只需补全差异逻辑避免重复造轮子。具体类ConcreteArrayList、HashMap、TreeSet等提供真正的存储结构和算法。这种设计让你写业务代码时面向接口编程ListUser 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的子接口。它的根就是MapK,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、LinkedListSet无序HashSet禁止不支持HashSet、TreeSetQueue按排队规则看实现一般不支持ArrayDeque、PriorityQueue“有序在List里指插入顺序可复现、可用下标访问Set的HashSet不保证顺序TreeSet按比较器排但也不是插入序”。这点极易混淆。四、时间复杂度速查表背下来这是集合框架最实用的性能地图建议存下来操作ArrayListLinkedListHashMapTreeMapHashSet按索引查 get(i)O(1)O(n)———末尾增 addO(1)*O(1)O(1)*O(log n)O(1)*中间插/删O(n)O(1)**———查 containO(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遍历ListStringlistnewArrayList(List.of(a,b,c));IteratorStringitlist.iterator();while(it.hasNext()){Stringsit.next();if(b.equals(s))it.remove();// 安全删除}注意遍历时用集合自身的remove()会抛ConcurrentModificationException必须用迭代器的remove()或用for-each 提前收集再删或用Iterator。这正是后面调优篇要细讲的fail-fast机制。Map没有Iterator但entrySet()返回SetMap.EntryK,V一样能迭代for(Map.EntryString,Integere: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等写统计逻辑极爽。StreamAPI 让集合进入流水线时代list.stream().filter(...).map(...).collect(...)。例子按城市统计人数MapString,Longcntusers.stream().collect(Collectors.groupingBy(User::getCity,Collectors.counting()));但parallelStream()不是银弹——共享可变状态、线程不安全集合、小数据量都会让它反而不如串行的调优篇会专门拆。七、为什么面向接口编程这么重要回到开头那句ListUser list new ArrayList()。当你把方法参数写成ListT而不是ArrayListT调用方可以传LinkedList、CopyOnWriteArrayList、Collections.emptyList()你的方法完全不用改。这是集合框架分层带来的最大红利解耦使用方式和底层实现。同理返回Map的方法内部想换成ConcurrentHashMap提升并发对外签名不变。写 SDK、写业务分层时这个习惯能少写无数适配代码。总结集合框架 两大根Collection / Map 三层结构接口 / 抽象类 / 实现 一套统一迭代器。记住List 有序可重复、Set 不可重复、Map 是键值对且不属于 Collection再配合复杂度速查表你就拿到了整个框架的地图。后续源码篇都是在给这张地图填充细节。