📄 一句话概括
集合章八节收拢:存得下 → 用得顺 → 加工得漂亮。这章也是跨章收网大户——4.5 的 hashCode 搭伴规矩、4.7 的 Lambda、6.1 的自动装箱,全在集合里正式上岗。
1. 八节串线
| 节 | 干什么 | 收掉的旧账 |
|---|---|---|
| 7.1 集合概述 | 家族地图 + 第一个 ArrayList | 2.7 数组三痛点收网;6.1 自动装箱第一线上岗 |
| 7.2 Collection接口 | 总合同 + 六大通用方法 | 4.3 接口思想回收;4.5 equals 规矩第一次踩痛 |
| 7.3 List接口 | 有序带下标 + remove 歧义 | 2.6 重载依据实战;7.2 并发修改钩子收网 |
| 7.4 集合遍历 | 五姿势 + 迭代器原理 | 7.2/7.3 散点收拢;4.7 forEach+Lambda 混脸熟 |
| 7.5 Set接口 | 去重原理两道关卡 | 4.5 equals+hashCode 搭伴规矩正式收网 |
| 7.6 Map接口 | 键值对按名查 + 计数器套路 | 7.1 家族地图补全(Map 独立一棵树) |
| 7.7 常用工具类 | Collections / Arrays 外挂 | 2.7 打印地址旧账收网;6.3 工具类套路二次复用 |
| 7.8 Stream | 数据流水线三段式 | 4.7 Lambda 正式转正;7.4 forEach 进阶完整版 |
暗线一句话:这章学的是"怎么装一堆对象,还装得聪明"——从能用(ArrayList)到会选型(List/Set/Map 三口诀)到会加工(Stream 一行流)。
2. 概念速查 14 条
- 集合只能装对象——int 要变 Integer(6.1 自动装箱)。
- Collection 是接口,不能 new;Collections 是工具类,全 static。
- List:有序(存取一致)、带下标、可重复——ArrayList 默认首选。
- Set:不重复、无下标、顺序不保证——HashSet 查最快。
- Map:键唯一、值可重复,双列结构,不归 Collection 管。
- remove 歧义:
remove(int)按下标,remove(Object)按内容;List<Integer>删值要remove(Integer.valueOf(1))。 - contains 底层:挨个调 equals——自定义类不重写就比地址。
- 去重两道关卡:hashCode 定位桶 → equals 验明正身;重写 equals 必搭伴重写 hashCode。
- 遍历中删元素:只用
it.remove()或普通 for 倒着删;增强 for / 正着删都出事(modCount 账本机制)。 - Map 遍历:keySet / values / entrySet 三姿势,entrySet 效率最好。
- getOrDefault 计数器:
map.put(k, map.getOrDefault(k, 0) + 1)。 - Arrays.asList 定长:能 set 不能 add/remove;要增删包一层
new ArrayList<>(...)。 - binarySearch 前提:必须先 sort,乱序结果错且不报错。
- Stream 三段式:中间操作(备菜,返回新流)+ 终结操作(开火,一次性);惰性求值——没终结操作不执行。
3. 代码模板 4 段
模板一:ArrayList 基本功
List<String> list = new ArrayList<>();
list.add("甲"); // 增
list.add(1, "乙"); // 插队
String s = list.get(0); // 取
list.set(0, "丙"); // 改
list.remove(0); // 删(按下标)
for (String x : list) System.out.println(x); // 遍历
模板二:自定义类去重(4.5 收网款)
class Student {
String name;
// 构造方法省略……
@Override
public boolean equals(Object o) { /* 按内容比 */ }
@Override
public int hashCode() { /* 与 equals 搭伴生成 */ }
}
Set<Student> set = new HashSet<>(); // 同内容只留一份
模板三:Map 计数器
Map<String, Integer> counter = new HashMap<>();
for (String w : words) {
counter.put(w, counter.getOrDefault(w, 0) + 1);
}
// 遍历三姿势
for (Map.Entry<String, Integer> e : counter.entrySet()) {
System.out.println(e.getKey() + " 出现 " + e.getValue() + " 次");
}
模板四:Stream 一行流
List<Integer> result = scores.stream()
.filter(s -> s >= 80) // 中间操作,可继续链
.sorted()
.collect(Collectors.toList()); // 终结操作,装回新集合
4. 八大名坑回顾
List<Integer>里remove(1)删的是下标 1 不是值 1。- 增强 for 遍历中
list.remove()→ ConcurrentModificationException。 - 自定义类不重写 equals+hashCode → Set 去重失灵、Map 当键失灵。
Arrays.asList定长,add/remove 炸 UnsupportedOperationException。- binarySearch 不先 sort → 结果错误还不报错。
- Stream 流一次性,终结后复用炸 IllegalStateException。
- 只写中间操作不写终结操作 → 一行不执行(惰性)。
new ArrayList<int>()编译报错——泛型只能装引用类型。
5. 跨章连线
- 面向对象 → 集合:没有封装和多态就没有统一 Collection 合同;泛型
<String>是 4.4 类型安全的延伸。 - 异常 → 集合:ConcurrentModificationException、UnsupportedOperationException、ClassCastException 全是 5.2 收容所常客。
- Java API → 集合:自动装箱(6.1)、equals/hashCode(4.5→7.5)、Lambda(4.7→7.8)、工具类套路(6.3→7.7)。
- 数据结构视角:ArrayList 底层数组、LinkedList 链表、HashSet 哈希表——7.3/7.5 已经埋了理论钩子,后续数据结构专题会正式展开。
6. 毕业大题:单词计数器(综合全章)
import java.util.*;
import java.util.stream.*;
public class Final07 {
public static void main(String[] args) {
String text = "java is fun and java is powerful and java everywhere";
// ① 切词(6.8 split)→ 统计每个单词出现次数(Map 计数器)
String[] words = text.split(" ");
Map<String, Integer> counter = new HashMap<>();
for (String w : words) {
counter.put(w, counter.getOrDefault(w, 0) + 1);
}
// ② 去重看看有几种单词(Set)
Set<String> distinct = new HashSet<>(Arrays.asList(words));
System.out.println("共 " + distinct.size() + " 种单词");
// ③ Stream 挑出出现 ≥2 次的单词,按次数降序打印(7.8)
counter.entrySet().stream()
.filter(e -> e.getValue() >= 2)
.sorted((a, b) -> b.getValue() - a.getValue())
.forEach(e -> System.out.println(e.getKey() + ": " + e.getValue()));
}
}
// 输出:java: 3 and: 2 is: 2
❓ 毕业自检 5 题(点开对照)
- List/Set/Map 一句话选型口诀是什么?(排队 / 去重 / 按名查)
- 为什么自定义类进 HashSet 必须同时重写 equals 和 hashCode?(两道关卡:不同桶 equals 没出场机会)
- 遍历中安全删元素有哪两种正解?(it.remove() / 普通 for 倒着删)
- Stream 的中间操作和终结操作本质区别?(返回新流 vs 启动流水线;惰性 vs 开火)
Arrays.asList("a","b")能 set 能 add 吗?(能 set,add 炸——定长)
7. 下一步学什么
- ☑ 第八章 泛型开课 ✅ —— 8.1 泛型基础 点此复习:7.1 里"会认"的
<String>正式讲透——编译期安检 + 自己写泛型类 Box\<T>。
相关笔记
- 第四章 面向对象(下)/4.7 函数式编程:Lambda——Stream 的发动机
- 第五章 异常/5.6 本章小结:异常章小结——本章三个异常都从那来
- 第六章 Java API/6.9 本章小结:API 章小结——装箱与工具类套路在本章上岗
- 2.7 数组:集合的"前身",本章第一笔与最后一笔旧账都收在它头上