map用于一对一转换,不改变流结构;flatmap用于一对多展开并压平,适用于嵌套集合、optional解包及避免空指针。

Java Stream API 中的 map 和 flatMap 看似相似,实则分工明确:前者处理“一个变一个”,后者专攻“一个变多个再压平”。用错一个,轻则结果为空、结构嵌套混乱,重则抛 NullPointerException 或逻辑偏差。关键不在语法,而在你面对的数据形态。
map 适用场景:字段提取与简单转换
当你只需要从每个元素中取出某个值、做格式化或计算,且输出仍是一对一关系时,map 是自然选择。它不改变流的“层数”,也不增减元素个数。
- 从对象列表中提取 ID:
users.stream().map(User::getId) - 字符串转大写或长度:
words.stream().map(String::toUpperCase)或.map(String::length) - 数值平方或单位换算:
numbers.stream().map(x -> x * x)
flatMap 适用场景:拆解嵌套结构
当源数据本身是“集合的集合”(如 List<list>></list>),或一个元素天然对应多个结果(如一句话含多个词、一个订单含多个商品),就必须用 flatMap 来展开并合并。
- 二维列表展平:
nested.stream().flatMap(List::stream) - 句子拆词:
lines.stream().flatMap(s -> Arrays.stream(s.split(" "))) - 一对多关联展开:用户→地址列表 → 所有地址扁平为单一流
flatMap 处理 Optional 避免嵌套
当映射函数可能返回 Optional<t></t> 时,直接用 map 会得到 Optional<optional>></optional>,难以处理。而 flatMap 能自动“解开一层”,只保留有值的结果。
- 例如查找用户邮箱:
users.stream().flatMap(u -> u.getEmail().map(e -> Stream.of(e)).orElseGet(Stream::empty)) - 更简洁写法:
users.stream().flatMap(u -> u.getEmail().stream())(因Optional.stream()直接返回 0 或 1 个元素的流)
组合使用:先 filter 再 flatMap 更安全
flatMap 的映射函数若对 null 入参调用 .stream(),会 NPE。所以常见模式是先过滤掉无效项,再展开。
- 错误写法:
list.stream().flatMap(item -> item.getTags().stream())(item 或 getTags() 可能为 null) - 正确写法:
list.stream().filter(Objects::nonNull).map(Item::getTags).filter(Objects::nonNull).flatMap(List::stream) - 或一步到位:
list.stream().flatMap(item -> Optional.ofNullable(item).map(Item::getTags).orElse(Collections.emptyList()).stream())
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











