flatmap通过函数返回新stream来展开并合并流,不复制或修改原对象,仅传递引用;修改city字段会影响原对象,流终止后引用可达性取决于外部持有情况,应避免在mapper中做状态变更。

flatMap 处理对象引用的核心,是把每个元素“展开”成一个流,再把所有子流合并成一个扁平流。它不直接操作引用本身,而是通过函数返回一个新的 Stream,让 JVM 自动管理底层引用的传递与生命周期。
flatMap 如何对待对象引用
它不会复制对象,也不会修改原对象;传入的 mapper 函数接收原始对象(如 Country),你决定返回哪个 Stream(比如 country.cities().stream())。这个过程里,City 实例的引用被原样纳入新流——没有深拷贝,也没有脱离原有作用域。
- 若 City 是不可变对象或仅作读取,安全无副作用
- 若在 flatMap 内部修改了某个 City 的字段(如 city.setPopulation(0)),原对象会被改,因为引用指向同一内存地址
- 流终止后,这些引用是否可达,取决于外部变量是否还持有它们;flatMap 本身不延长也不截断生命周期
常见误用:别在 flatMap 里做状态变更
flatMap 设计为无副作用的转换操作。下面这种写法看似可行,实则破坏函数式原则且易出错:
- 错误:在 mapper 中调用 city.updateLastAccessed() 或向外部 List.add(city)
- 错误:返回 Stream.of(new City(...)) 却忽略原引用关系,导致业务逻辑断连
- 正确:只做映射和展平,例如 country -> country.cities().stream(),保持引用链清晰
结合 collect 或 forEach 时的引用注意点
flatMap 后接终端操作,引用行为延续不变:
- 用 collect(Collectors.toList()):得到的是原 City 对象的引用列表,不是副本
- 用 forEach(System.out::println):打印的是对象 toString(),背后仍是原引用
- 若需脱钩(如避免后续修改影响源数据),应在 flatMap 映射时显式构造新对象:city -> Stream.of(new City(city.name(), city.population()))
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











