java stream.peek()如何影响字节码?
据我所知,如果我有一个带有两个过滤器的流,它们将在字节码中与&&组合 比如说java stream.peek()如何影响字节码?,java,performance,java-8,java-stream,bytecode,Java,Performance,Java 8,Java Stream,Bytecode,据我所知,如果我有一个带有两个过滤器的流,它们将在字节码中与&&组合 比如说 IntStream.range(1,10) .filter(i -> i % 2 == 0) .filter(i -> i % 3 == 0) .sum(); 类似于i%2==0&&i%3==0 peek会影响这一点吗 如果你在第一个文件管理器之后偷看,你会得到2468个,如果你在第二个文件管理器之后偷看,你会得到6个(当然) 但如果你两个地方都看 IntStream.range(1,10)
IntStream.range(1,10)
.filter(i -> i % 2 == 0)
.filter(i -> i % 3 == 0)
.sum();
类似于i%2==0&&i%3==0
peek会影响这一点吗
如果你在第一个文件管理器之后偷看,你会得到2468个,如果你在第二个文件管理器之后偷看,你会得到6个(当然)
但如果你两个地方都看
IntStream.range(1,10)
.filter(integer -> integer % 2 == 0)
.peek(i-> System.out.print(i))
.filter(integer -> integer % 3 == 0)
.peek(i-> System.out.print(i))
.sum();
你得到24668
我的假设是,这一定意味着由于peek调用,操作以某种方式被分离。差不多
if(i%2==0)
peek
if(i%3==0)
这是真的吗?如果是真的,它会影响性能(我想不会)。它根本没有在字节码级别进行优化。每个lambda是一个单独的方法。Java依靠JVM在运行时透明地优化一切。正如您自己所见,
流
API是一个透明的API。接收任意的谓词
实例,可以通过lambda表达式或普通的类
(或枚举
来命名所有可能性)
如果您随后两次调用filter
,则底层实现可以通过调用将它们连接到单个筛选器,但对于通过lambda表达式实现的谓词,无论是否调用,都不会产生任何后果
与自定义谓词
实现不同,自定义谓词
实现可以覆盖和
方法,并在识别第二个谓词
实现时提供优化的内容,为lambda表达式生成的类不会覆盖任何默认
方法,但是只有一个abstract
函数方法,这里是Predicate.test
,因此在本例中,调用和将得到default
方法返回的内容,一个新的谓词
,它包含对两个源谓词的引用并将它们组合在一起,很像一个不使用谓词的流实现,
也可以
因此,这些可能的实现之间没有实质性的区别,如果您插入另一个动作,比如传递给peek
的Consumer
,则没有实质性的区别。当然,它现在比不执行此操作做得更多,因此它对性能有影响,但与谓词无关
但您普遍的误解似乎是您认为以下两者之间存在重大差异:
for(int i=1; i<10; i++) {
if(i%2==0 && i%3==0)
System.out.print(i);
}
正如您所看到的,print语句的插入会导致print语句的插入,不会更多,也不会更少。或者,换句话说,&&
操作符不是一种神奇的融合,它不同于两个嵌套的if
语句。两者在语义和字节码上都完全相同
同样的情况也适用于流API的使用,尽管如此,代码将更加复杂,因为条件表达式表示为谓词
实例,而插入的语句是消费者
s。但在最好的情况下,热点优化器将为流变量生成与循环变量完全相同的优化本机代码。我认为lambda编译为合成方法,而不是类(参考“为lambda表达式生成的类”)。哪个是正确的?谢谢你详细的回答,这正是我想知道的。我期望两者的表现相同,我只是不确定我的假设是否正确。看起来是这样,但现在我对原因有了更深的理解。谢谢大家!@erickson:lambda表达式被编译成合成方法,JRE将为其生成一个类,该类实现函数接口并调用该合成方法。生成的类的许多属性都是故意未指定的,但它们不重写默认
方法的事实是:“该类不重写目标函数接口类型或上述其他接口类型的其他方法,尽管它可能重写对象
类的方法”好的,这是有道理的。我意识到必须有一个对象来实现接口,但我不确定是否有某种反射/动态代理实现,或者在编译时是否有一个合成类。
for(int i=1; i<10; i++) {
if(i%2==0) {
System.out.print(i);
if(i%3==0)
System.out.print(i);
}
}