在此Java流使用中是否应该调用映射操作?

在此Java流使用中是否应该调用映射操作?,java,java-8,java-stream,Java,Java 8,Java Stream,假设此用法在逻辑上(即,它计算所需的布尔值)正确: 与此相比: boolean matches = someObjectList .stream() .map(myObjType -> myObjType.getSomeStatusString()) .anyMatch(status -> !status.equals("someStatus")); 一种形式客观上比另一种好吗?字节码之间有显著差异吗?一个是反

假设此用法在逻辑上(即,它计算所需的布尔值)正确:

与此相比:

boolean matches = someObjectList
            .stream()
            .map(myObjType -> myObjType.getSomeStatusString())
            .anyMatch(status -> !status.equals("someStatus"));

一种形式客观上比另一种好吗?字节码之间有显著差异吗?一个是反模式吗?是否有一些Java优化器使一个比另一个更好?我对基于观点的差异不感兴趣,比如第一种更具可读性,因为不同的读者可能会有所不同。

我偶然发现了我想要的答案

选择的答案(讨论垃圾收集)部分说:

在热点JVM之类的实现中,每个线程都为新对象使用线程本地分配缓冲区(TLAB)。一旦TLAB已满,它将从分配空间(也称为Eden空间)获取一个新的TLAB。如果没有可用的,将触发垃圾回收。现在,所有线程不太可能同时到达TLAB的末尾。因此,对于其他线程来说,此时它们的TLAB中仍有一些空间,如果它们分配了更多仍然适合剩余空间的对象,则不会有任何区别

可能令人惊讶的结论是,并非每个分配的对象都会对垃圾收集产生影响,也就是说,由未触发下一个gc的线程分配的纯本地对象可能是完全免费的


我的结论是,第二种方法中“额外”对象的创建没有客观成本。因此,我不认为一种形式比另一种形式有任何客观的好处。

这篇文章是在征求意见,因此是离题的。使用
map
可以使它清晰易读。从性能上看,它们应该是相同的,或者可能是第一种形式通过稍微少做一些操作而稍微快一些。第一个对我来说比较容易。如果使用方法引用,第二行代码会更容易阅读,但是它不能。如果你想要更少的代码行,就使用第一行代码。如果您想减少其他开发人员的阅读时间,请选择第二个。但这完全取决于编码惯例或您的意见。@JoeG您并没有定义优越性。如果没有任何衡量标准,这个问题是基于意见的。如果您想在比较中了解每种方法的优缺点,请询问。创建了哪些“额外”对象?我相信.map操作将需要自己的字符串对象,它将无法像“get”调用那样使用对字符串的引用(即没有.map的代码)。但是我不知道这是为什么我首先问这个问题的动机。好吧,
getSomeStatusString
方法在任何一种方式下对每个对象调用一次,因此无论哪种方式都会创建相同的字符串对象(除非它们在调用
getSomeStatusString
之前已经存在)。是的,“get”方法的目的是作为POJO get,因此这些字符串已经存在了,因此,出于稍微错误的原因,这是正确的结论。如果有额外的字符串创建,则会产生不同,因为每个元素的字符串创建可能会很昂贵(字符串创建意味着复制字符内容,这使得它比普通对象创建更昂贵)。但是,在第二个变体中没有创建每个元素的字符串,而是为整个流创建了更多的对象,
函数
实例和流实现特定的对象,以记住
映射
操作已链接。这些正是根本不重要的对象。
boolean matches = someObjectList
            .stream()
            .map(myObjType -> myObjType.getSomeStatusString())
            .anyMatch(status -> !status.equals("someStatus"));