☕ 第七章 集合
📄 一句话概括

集合章八节收拢:存得下 → 用得顺 → 加工得漂亮。这章也是跨章收网大户——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 条

  1. 集合只能装对象——int 要变 Integer(6.1 自动装箱)。
  2. Collection 是接口,不能 new;Collections 是工具类,全 static。
  3. List:有序(存取一致)、带下标、可重复——ArrayList 默认首选。
  4. Set:不重复、无下标、顺序不保证——HashSet 查最快。
  5. Map:键唯一、值可重复,双列结构,不归 Collection 管。
  6. remove 歧义:remove(int) 按下标,remove(Object) 按内容;List<Integer> 删值要 remove(Integer.valueOf(1))。
  7. contains 底层:挨个调 equals——自定义类不重写就比地址。
  8. 去重两道关卡:hashCode 定位桶 → equals 验明正身;重写 equals 必搭伴重写 hashCode。
  9. 遍历中删元素:只用 it.remove() 或普通 for 倒着删;增强 for / 正着删都出事(modCount 账本机制)。
  10. Map 遍历:keySet / values / entrySet 三姿势,entrySet 效率最好。
  11. getOrDefault 计数器:map.put(k, map.getOrDefault(k, 0) + 1)。
  12. Arrays.asList 定长:能 set 不能 add/remove;要增删包一层 new ArrayList<>(...)。
  13. binarySearch 前提:必须先 sort,乱序结果错且不报错。
  14. 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. 八大名坑回顾

  1. List<Integer> 里 remove(1) 删的是下标 1 不是值 1。
  2. 增强 for 遍历中 list.remove() → ConcurrentModificationException。
  3. 自定义类不重写 equals+hashCode → Set 去重失灵、Map 当键失灵。
  4. Arrays.asList 定长,add/remove 炸 UnsupportedOperationException。
  5. binarySearch 不先 sort → 结果错误还不报错。
  6. Stream 流一次性,终结后复用炸 IllegalStateException。
  7. 只写中间操作不写终结操作 → 一行不执行(惰性)。
  8. new ArrayList<int>() 编译报错——泛型只能装引用类型。

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 题(点开对照)
  1. List/Set/Map 一句话选型口诀是什么?(排队 / 去重 / 按名查)
  2. 为什么自定义类进 HashSet 必须同时重写 equals 和 hashCode?(两道关卡:不同桶 equals 没出场机会)
  3. 遍历中安全删元素有哪两种正解?(it.remove() / 普通 for 倒着删)
  4. Stream 的中间操作和终结操作本质区别?(返回新流 vs 启动流水线;惰性 vs 开火)
  5. Arrays.asList("a","b") 能 set 能 add 吗?(能 set,add 炸——定长)

7. 下一步学什么

相关笔记