为何Map的Stream调用.map修改不生效?两段代码差异问询
嘿,这个问题其实戳中了Java Stream的核心特性之一——惰性求值,咱们一步步拆解来看:
一、第一段代码修改未生效的原因
首先得记住:Java Stream的中间操作(比如map)是惰性的——它们不会立刻执行逻辑,只有当你调用了**终端操作(比如forEach、collect)**的时候,整个Stream流水线才会真正启动执行。
第一段代码里只有map这一个中间操作,完全没有终端操作触发执行。换句话说,element.setValue(100)这行代码根本就没被运行过,自然不会对原Map产生任何修改。
二、第二段代码修改生效的原因
第二段代码在map后面加了forEach——这是一个典型的终端操作。当JVM检测到终端操作时,才会从头到尾执行整个Stream流程:遍历entrySet()里的每个Entry,执行map中的setValue(100)逻辑,再把结果传给forEach处理。这时候setValue真正被调用了,Map里的元素也就被成功修改了。
三、为什么第二段代码只打印值而非完整Entry?
这得看Map.Entry.setValue()方法的返回值规则:这个方法会返回该Entry被修改前的旧值。而map操作的作用是把流中的每个元素转换成另一个元素——这里就是把每个Map.Entry对象转换成setValue(100)的返回值(也就是旧的Integer数值)。
所以经过map之后,Stream里的元素类型已经从Map.Entry变成了Integer,forEach打印的自然就是这些旧数值,而非完整的键值对。
如果想打印修改后的完整Entry,你可以改用peek操作(它只对元素执行操作,不会改变流的元素类型):
stringIntegerMap.entrySet().stream() .peek(element -> element.setValue(100)) .forEach(System.out::println);
内容的提问来源于stack exchange,提问作者user9016902

