举个例子:
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>
,而不是在运算符&&
上将其拆分,略微缩短字节码。