当前位置: 首页 > news >正文

Java8核心能力篇-Lambda-Stream-Optional与日期时间

前言

"很多人说自己会 Java 8,其实只是会写几个stream()。"

Java 8 真正带来的变化,不只是多了几个 API,而是把整个编码风格往函数式、声明式和不可变方向推了一大步。

这一篇不追求大而全,只讲最该掌握的 5 个核心能力:Lambda、Stream、方法引用、Optional 和 DateTime API。把这几个点吃透,你的 Java 代码风格会明显上一个台阶。


一、Lambda 表达式:函数式编程的起点

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);

📌 注意点

  • Lambda 捕获的局部变量必须是 effectively final
  • 参数类型通常可以省略,由编译器推断
  • 单表达式 Lambda 可以省略大括号和return

二、Stream API:让集合操作更像“描述意图”

Stream 最重要的价值,不是炫技,而是把“做什么”从“怎么做”里拆出来。

常见操作

操作类型方法说明
中间操作filter()过滤元素
中间操作map()元素转换
中间操作flatMap()展平嵌套集合
中间操作distinct()去重
中间操作sorted()排序
终止操作collect()收集结果
终止操作findFirst()取第一个元素
终止操作toList()收集为列表,Java 16+

1. 对象转换

List<ChatSessionResponse> responses = page.getRecords().stream() .map(this::toSessionResponse) .toList();

如果还在 Java 8 环境,可以写成:

List<ChatSessionResponse> responses = page.getRecords().stream() .map(this::toSessionResponse) .collect(Collectors.toList());

2. 转成 Map

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 ));

3. 分组聚合

Map<Long, List<String>> capabilitiesByModel = capabilities.stream() .collect(Collectors.groupingBy( AiModelCapabilityEntity::getModelId, Collectors.mapping( AiModelCapabilityEntity::getCapabilityType, Collectors.toList() ) ));

4. flatMap 展平

List<Long> chunkIds = refsByMessageId.values().stream() .flatMap(List::stream) .map(ChatAnswerReferenceEntity::getChunkId) .toList();

5. 统计计算

long totalPromptTokens = messages.stream() .map(ChatMessageEntity::getPromptTokens) .filter(Objects::nonNull) .mapToLong(Integer::longValue) .sum();

📌 Stream 使用建议

  • 不要把 Stream 当成“链式炫技工具”
  • 避免在 Lambda 中修改外部状态
  • parallelStream()不是禁用项,但不要默认觉得它更快,必须按场景评估
  • 一个 Stream 只能消费一次

三、方法引用:能省则省,但别写错

方法引用是 Lambda 的语法糖,本质没变,只是更简洁。

类型语法示例
静态方法引用ClassName::staticMethodObjects::nonNull
特定对象实例方法引用instance::methodthis::toSessionResponse
任意对象实例方法引用ClassName::methodString::toUpperCase
构造方法引用ClassName::newArrayList::new

.filter(Objects::nonNull) .map(this::toSessionResponse) .map(ChatMessageEntity::getId)

真正的构造方法引用应该长这样:

Supplier<List<String>> supplier = ArrayList::new;

Function.identity()不是构造方法引用,它只是“返回参数本身”的函数。


四、Optional:少写空指针判断,但别滥用

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()
  • 不要为了“显得高级”到处包一层 Optional

五、DateTime API:真正该淘汰的是旧时间 API

java.time是 Java 8 最应该全面拥抱的一套 API。

用途
LocalDate日期
LocalTime时间
LocalDateTime日期时间
InstantUTC 时间点
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/Calendar
  • 涉及时区时,优先明确使用InstantZonedDateTime
  • 数据库存储和序列化时要确认时区策略一致

总结

Java 8 最核心的升级,不是某个单独 API,而是编码思维的变化:

  1. Lambda 让行为可传递
  2. Stream 让集合操作更声明式
  3. 方法引用让样板代码更少
  4. Optional 让空值表达更明确
  5. DateTime API 让时间处理终于变得可靠

如果你想真正跨过“会写 Java”和“会写现代 Java”的分界线,这 5 个点必须熟。

http://www.cnnetsun.cn/news/1675970.html

相关文章:

  • Claude Code每日更新速览(v2.1.91)-2026/04/03
  • HAA固件深度解析:从架构设计到核心组件实现原理
  • PromptSource模板推荐系统:基于任务自动选择最优提示的终极指南
  • AD9959 FPGA驱动开发:实现全通道FPA自由调控与任意FPGA移植
  • ai辅助开发:让快马平台智能诊断并生成最优的wsl ubuntu环境配置方案
  • S-UI缓存策略设计:API响应与静态资源缓存
  • OpenClaw内存优化:Qwen3-14B镜像在120GB内存下的性能调优
  • 基于三角波注入的永磁同步电机参数辩识:Simulink仿真模型及相关文章
  • hello-uniapp分包加载策略:解决小程序体积过大问题
  • S-UI数据库读写分离:提升查询性能的架构设计
  • ESP32 BLE鼠标库:支持高精度水平/垂直滚轮的HID设备实现
  • PromptSource性能瓶颈分析:大规模提示集合的优化方向
  • 10个EmojiPackage表情包创意用法:让社交媒体沟通更有趣
  • DS4Windows:在Windows上完美使用PlayStation手柄的终极解决方案
  • DeepSeek 总结的pgEdge for Postgres 的 MCP 服务器
  • AI大模型应用开发学习路线(2026最新)从零基础入门到精通,非常详细收藏我这一篇就够了!
  • FluidTransitions 插值器系统:位置、缩放、旋转动画的底层实现
  • 飞书CLI开源,AI办公新突破?
  • 从Java全栈到Vue3实战:一次真实面试中的技术对话
  • PDFKit核心源码分析:揭秘HTML到PDF的转换魔法
  • Qwen3.5-35B-A3B-AWQ-4bit政务场景落地:政策文件附图解读+办事流程图转化
  • 2025届最火的六大AI科研平台实际效果
  • 基础入门-Shell脚本编程-编写简单的自动化脚本
  • 外贸参展的十种实用小礼品推荐
  • 某型全任务直升机飞行模拟器总体设计方案
  • 向量数据库:大模型的高效外存
  • kprobe函数入口时的汇编跳板执行流程与栈帧机制
  • CPU与操作系统【简单的认识理解】
  • 【C++27静态反射工业落地白皮书】:揭秘航天嵌入式系统中零运行时开销序列化实现路径
  • 论文查重还在花冤枉钱?Paperxie 免费查重,本科生的毕业省钱神器