Java 8 不只是引入 Lambda,也补齐了很多官方库能力。Optional、Stream API 和 java.time 是日常代码里最常用的三类变化。用得好,代码会更清晰;用得过头,也会变得难读。
Optional 用来表达可能为空
Optional 的价值是把“这个值可能不存在”显式写进类型里,减少散落在代码里的 null 判断。
适合的场景包括:
- 方法返回值可能为空。
- 调用方需要明确处理缺失分支。
- 多步转换中希望链式处理空值。
不适合的场景也要避免:不要把实体字段大量改成 Optional,不要把参数都包成 Optional,不要为了不用 if 写出更绕的链式调用。
Optional 是表达语义的工具,不是消灭所有空判断的工具。
Stream 适合集合转换和聚合
Stream API 让集合过滤、映射、分组、求和更直接。
例如从任务列表里筛选开放状态,再统计分数:
long total = tasks.stream()
.filter(task -> task.getStatus() == Status.OPEN)
.mapToInt(Task::getPoints)
.sum();
这类代码比手写循环更能表达“做什么”。但 Stream 也有边界:复杂分支、需要中途调试、多层副作用、异常处理复杂时,普通循环可能更清楚。
中间操作是惰性的,终止操作才会真正执行。理解这一点,才能避免以为 filter、map 会立刻产生结果。
并行 Stream 要谨慎
parallel() 看起来很方便,但并行不是免费加速。
它有拆分任务、线程调度、合并结果的成本。数据量小、每个元素计算很轻、存在共享状态、涉及 I/O 或锁竞争时,并行 Stream 可能更慢,也更难排查。
适合并行的任务通常是:数据量足够大、每个元素计算独立、没有共享可变状态、合并成本低。
java.time 解决旧时间 API 的坑
Java 8 的 java.time 吸收了 Joda-Time 的经验,提供了更清晰的日期时间模型。
常见类型可以这样理解:
LocalDate:只有日期,没有时间和时区。LocalTime:只有时间。LocalDateTime:日期加时间,但没有时区。Instant:时间线上的瞬间,适合存储和比较。ZonedDateTime:带时区的日期时间。Duration和Period:表达时间间隔。
新 API 大多不可变,修改会返回新对象,减少了旧 Date、Calendar 那类可变对象带来的混乱。
实用结论
Java 8 库特性适合用来提升表达力。Optional 表达缺失,Stream 表达集合流水线,java.time 表达清晰的日期时间语义。
不要为了“新写法”牺牲可读性。能让意图更明确、边界更清楚的地方就用;复杂到调用方需要来回猜执行顺序时,回到朴素写法反而更稳。




