JDK 8 一页速查卡
函数式与流
3四种写法与目标类型
Function<String, Integer> len = String::length;
BiFunction<Integer, Integer, Integer> add = (a, b) -> a + b;
Supplier<List<String>> list = ArrayList::new;
Runnable r = () -> System.out.println("run");
Lambda 只能绑定函数式接口;参数类型可省略,返回类型由上下文推断。
三段式流水线
List<String> out = names.stream()
.filter(n -> n.length() > 3)
.map(String::toUpperCase)
.sorted()
.collect(Collectors.toList());
中间操作惰性;终止操作才执行;流只能消费一次。
parallel 的边界
- 适合:大数据量、CPU 密集、无状态、可结合的操作
- 不适合:I/O、小数据、共享可变状态、强顺序依赖
- 默认使用
ForkJoinPool.commonPool(),并行度约为 CPU-1
并行流不会自动更快;forEach 不保证顺序,需要顺序时用 forEachOrdered。
Optional 与时间
3只放在返回值上
Optional<User> user = repo.find(id);
String name = user.map(User::name).orElse("anonymous");
不要用于字段、参数、集合元素;Optional.of(null) 直接 NPE。
orElse vs orElseGet
opt.orElse(expensive()); // 总会求值
opt.orElseGet(() -> expensive()); // 为空才求值
opt.orElseThrow(() -> new IllegalStateException());
默认值昂贵或有副作用时,必须用 orElseGet。
类型地图
Instant:时间线上的点,UTC 纪元LocalDate/LocalDateTime:无时区的人类时间ZonedDateTime:带 ZoneId 与 DST 规则Duration表示时长,Period表示日期跨度
全部不可变;格式化用 DateTimeFormatter,可复用。
接口与集合
3默认方法与冲突
interface A { default String tag() { return "A"; } }
interface B { default String tag() { return "B"; } }
class C implements A, B {
public String tag() { return A.super.tag() + B.super.tag(); }
}
类优先于接口;子接口优先于父接口;否则必须显式覆盖。
接口静态方法
interface Named {
static Named of(String name) { return () -> name; }
}
Named n = Named.of("Ada"); // 只能通过接口名调用
static 方法不被实现类继承;接口不能有实例字段。
阈值速记
- 默认容量 16,负载因子 0.75,阈值 12
- 扩容翻倍;容量必须是 2 的幂
- 链表超过 8 且容量 ≥ 64 才树化
- 扩容拆分时树节点 ≤ 6 退回链表
第 9 个节点插入才触发树化;容量不足 64 时先扩容。
迁移与运行时
3PermGen 已移除
-XX:MetaspaceSize=64m
-XX:MaxMetaspaceSize=256m
Metaspace 在本地内存;默认不设上限。-XX:MaxPermSize 在 8 只警告,9+ 启动失败。
class 版本与 source
javac -source 1.8 -target 1.8 App.java
javap -verbose App.class | grep major # 52
JDK 8 没有 --release;-source 1.7 下 lambda 直接编译失败。
8 里没有这些
var(10)、List.of/Map.of(9)Files.readString、String.isBlank、HttpClient(11)record(16)、sealed(17)、文本块(15)Stream.toList(16)、Optional.isEmpty(11)
写 JDK 8 代码时,IDE 的 SDK 与语言级别都要锁到 8。
4 个最容易记错的点TRAPS
JDK 8 在桶内已有 8 个节点、插入第 9 个时才调用 treeifyBin;容量小于 64 时先扩容,不会树化。
orElse(expensive()) 在 Optional 有值时也会执行参数表达式;需要惰性求值用 orElseGet。
在 parallel stream 里对 ArrayList add、对计数器 ++ 都会丢更新;用 collect/reduce 或线程安全结构,并注意 commonPool 被阻塞。
JDK 8 会打印 ignoring option 并继续启动;JDK 9+ 变成 Unrecognized VM option,直接失败。升级时应删除,而不是保留。
继续深入NEXT
内容基于本机 JDK 1.8.0_281 编译/运行验证;版本边界按 JDK 8 正式 API 标注,未使用 9+ 能力。