[英]Does Java compiler optimize stream filtering?
我们有一个案例:
x.stream().filter(X::isFlag).filter(this::isOtherFlag).reduce(...)
它与这个不同吗?
x.stream().filter(predicate(X::isFlag).and(this::isOtherFlag)).reduce(...)
从功能上讲,这两个陈述是等价的。 但是,请考虑以下两个代码块及其各自的字节码:
public static void main(String[] args) {
List<String> list = List.of("Seven", "Eight", "Nine");
list.stream().filter(s -> s.length() >= 5)
.filter(s -> s.contains("n"))
.forEach(System.out::println);
}
public static void main(java.lang.String[]);
Code:
0: ldc #16 // String Seven
2: ldc #18 // String Eight
4: ldc #20 // String Nine
6: invokestatic #22 // InterfaceMethod java/util/List.of:(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/util/List;
9: astore_1
10: aload_1
11: invokeinterface #28, 1 // InterfaceMethod java/util/List.stream:()Ljava/util/stream/Stream;
16: invokedynamic #35, 0 // InvokeDynamic #0:test:()Ljava/util/function/Predicate;
21: invokeinterface #36, 2 // InterfaceMethod java/util/stream/Stream.filter:(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;
26: invokedynamic #42, 0 // InvokeDynamic #1:test:()Ljava/util/function/Predicate;
31: invokeinterface #36, 2 // InterfaceMethod java/util/stream/Stream.filter:(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;
36: getstatic #43 // Field java/lang/System.out:Ljava/io/PrintStream;
39: invokedynamic #52, 0 // InvokeDynamic #2:accept:(Ljava/io/PrintStream;)Ljava/util/function/Consumer;
44: invokeinterface #53, 2 // InterfaceMethod java/util/stream/Stream.forEach:(Ljava/util/function/Consumer;)V
49: return
-
public static void main(String[] args) {
List<String> list = List.of("Seven", "Eight", "Nine");
list.stream().filter(s -> s.length() >= 5 && s.contains("n"))
.forEach(System.out::println);
}
public static void main(java.lang.String[]);
Code:
0: ldc #16 // String Seven
2: ldc #18 // String Eight
4: ldc #20 // String Nine
6: invokestatic #22 // InterfaceMethod java/util/List.of:(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/util/List;
9: astore_1
10: aload_1
11: invokeinterface #28, 1 // InterfaceMethod java/util/List.stream:()Ljava/util/stream/Stream;
16: invokedynamic #35, 0 // InvokeDynamic #0:test:()Ljava/util/function/Predicate;
21: invokeinterface #36, 2 // InterfaceMethod java/util/stream/Stream.filter:(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;
26: getstatic #42 // Field java/lang/System.out:Ljava/io/PrintStream;
29: invokedynamic #51, 0 // InvokeDynamic #1:accept:(Ljava/io/PrintStream;)Ljava/util/function/Consumer;
34: invokeinterface #52, 2 // InterfaceMethod java/util/stream/Stream.forEach:(Ljava/util/function/Consumer;)V
39: return
我们可以看到,在第二个例子中,缺少对invokedynamic
和invokeinterface
一次调用(这是有意义的,因为我们省略了对filter
的调用)。 我确信有人可以帮助我对这个字节码进行静态分析(如果需要,我可以发布详细文件),但Java编译器明确将单个调用filter
为单个Predicate<String>
而不是将其拆分为operator &&
,略微缩短字节码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.