弗兰的悲惨之旅
99.73M · 2026-04-04
"很多人说自己会 Java 8,其实只是会写几个 stream()。"
Java 8 真正带来的变化,不只是多了几个 API,而是把整个编码风格往函数式、声明式和不可变方向推了一大步。
这一篇不追求大而全,只讲最该掌握的 5 个核心能力:Lambda、Stream、方法引用、Optional 和 DateTime API。把这几个点吃透,你的 Java 代码风格会明显上一个台阶。

Lambda 是 Java 8 最关键的起点,也是后面 Stream、Optional 等特性的基础。
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("Hello");
}
};
Runnable r2 = () -> System.out.println("Hello");
实战里最常见的价值,不是“少写几行”,而是把行为当参数传进去。
new LambdaQueryWrapper<SysUserEntity>()
.eq(StringUtils.hasText(status), SysUserEntity::getStatus, status)
.eq(SysUserEntity::getDeleted, Boolean.FALSE)
.and(StringUtils.hasText(keyword), wrapper -> wrapper
.like(SysUserEntity::getUsername, keyword)
.or()
.like(SysUserEntity::getDisplayName, keyword)
.or()
.like(SysUserEntity::getMobile, keyword))
.orderByDesc(SysUserEntity::getId);
注意点
returnStream 最重要的价值,不是炫技,而是把“做什么”从“怎么做”里拆出来。
| 操作类型 | 方法 | 说明 |
|---|---|---|
| 中间操作 | filter() | 过滤元素 |
| 中间操作 | map() | 元素转换 |
| 中间操作 | flatMap() | 展平嵌套集合 |
| 中间操作 | distinct() | 去重 |
| 中间操作 | sorted() | 排序 |
| 终止操作 | collect() | 收集结果 |
| 终止操作 | findFirst() | 取第一个元素 |
| 终止操作 | toList() | 收集为列表,Java 16+ |
List<ChatSessionResponse> responses = page.getRecords().stream()
.map(this::toSessionResponse)
.toList();
如果还在 Java 8 环境,可以写成:
List<ChatSessionResponse> responses = page.getRecords().stream()
.map(this::toSessionResponse)
.collect(Collectors.toList());
Map<Long, ChunkEntity> chunkMap = chunkMapper.selectBatchIds(chunkIds)
.stream()
.collect(Collectors.toMap(
ChunkEntity::getId,
Function.identity()
));
如果 key 可能重复,要显式写合并逻辑:
.collect(Collectors.toMap(
Entity::getId,
Function.identity(),
(existing, replacement) -> existing
));
Map<Long, List<String>> capabilitiesByModel = capabilities.stream()
.collect(Collectors.groupingBy(
AiModelCapabilityEntity::getModelId,
Collectors.mapping(
AiModelCapabilityEntity::getCapabilityType,
Collectors.toList()
)
));
List<Long> chunkIds = refsByMessageId.values().stream()
.flatMap(List::stream)
.map(ChatAnswerReferenceEntity::getChunkId)
.toList();
long totalPromptTokens = messages.stream()
.map(ChatMessageEntity::getPromptTokens)
.filter(Objects::nonNull)
.mapToLong(Integer::longValue)
.sum();
Stream 使用建议
parallelStream() 不是禁用项,但不要默认觉得它更快,必须按场景评估方法引用是 Lambda 的语法糖,本质没变,只是更简洁。
| 类型 | 语法 | 示例 |
|---|---|---|
| 静态方法引用 | ClassName::staticMethod | Objects::nonNull |
| 特定对象实例方法引用 | instance::method | this::toSessionResponse |
| 任意对象实例方法引用 | ClassName::method | String::toUpperCase |
| 构造方法引用 | ClassName::new | ArrayList::new |
.filter(Objects::nonNull)
.map(this::toSessionResponse)
.map(ChatMessageEntity::getId)
真正的构造方法引用应该长这样:
Supplier<List<String>> supplier = ArrayList::new;
Function.identity() 不是构造方法引用,它只是“返回参数本身”的函数。
Optional 是 Java 8 引入的容器类,用于表达“这个值可能不存在”。
Optional<String> opt1 = Optional.of("hello");
Optional<String> opt2 = Optional.ofNullable(maybeNull);
Optional<String> opt3 = Optional.empty();
常见写法:
String value = opt.orElse("默认值");
String value2 = opt.orElseGet(this::computeDefaultValue);
String value3 = opt.orElseThrow(() -> new BusinessException("值不存在"));
ifPresentOrElse() 也很好用,但这里要注意版本:
opt.ifPresentOrElse(
value -> System.out.println("值: " + value),
() -> System.out.println("无值")
);
这个方法是 Java 9 才加的,不是 Java 8。
Stream 配合 Optional 的典型用法:
public EmbeddingModelClient getClient(String providerCode) {
return clients.stream()
.filter(client -> client.supports(providerCode))
.findFirst()
.orElseThrow(() -> new BusinessException("当前未实现该模型提供方的客户端"));
}
Optional 注意点
get()java.time 是 Java 8 最应该全面拥抱的一套 API。
| 类 | 用途 |
|---|---|
LocalDate | 日期 |
LocalTime | 时间 |
LocalDateTime | 日期时间 |
Instant | UTC 时间点 |
Duration | 时间段 |
ZonedDateTime | 带时区时间 |
实战里最常见的写法:
LocalDateTime now = LocalDateTime.now();
Instant start = Instant.now();
int latencyMs = (int) Duration.between(start, Instant.now()).toMillis();
LocalDateTime staleBefore = LocalDateTime.now().minus(Duration.ofMinutes(5));
String datePath = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
配合 Spring 或 Redis 也很自然:
Duration ttl = Duration.ofSeconds(refreshTokenTtlSeconds);
stringRedisTemplate.opsForValue().set(key, value, ttl);
DateTime API 注意点
Date/CalendarInstant 或 ZonedDateTimeJava 8 最核心的升级,不是某个单独 API,而是编码思维的变化:
如果你想真正跨过“会写 Java”和“会写现代 Java”的分界线,这 5 个点必须熟。
欢迎关注公众号 FishTech Notes,一块交流使用心得!