我看到 Let’s Get Lazy: Explore the Real Power of Streams youtube 上的视频 (venkat subramaniam)。 (大约 26-30 分钟)
在例子中,一个for循环:
List<Integer> numbers = Arrays.asList(1, 2, 3, 5, 4, 6, 7, 8, 9, 10);
int result = 0;
for(int e: values){
if(e > 3 && e % 2 == 0){
result = e * 2;
break;
}
}
有8个“单元操作”
根据他的例子:
public class MainClass {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 5, 4, 6, 7, 8, 9, 10);
System.out.println(
numbers.stream()
.filter(e -> e > 3)
.filter(e -> e % 2 == 0)
.map(e -> e * 2)
.findFirst()
.orElse(0)
);
}
}
这段代码看起来有 21 个“单元操作”。
然后他推荐使用这段代码:
public class MainClass {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 5, 4, 6, 7, 8, 9, 10);
System.out.println(
numbers.stream()
.filter(MainClass::isGT3)
.filter(MainClass::isEven)
.map(MainClass::doubleIt)
.findFirst()
.orElse(0)
);
}
private static int doubleIt(Integer e) {
return e * 2;
}
private static boolean isEven(Integer e) {
return e % 2 == 0;
}
private static boolean isGT3(Integer e) {
return e > 3;
}
}
我真的很想明白,这怎么能证明有8个单元运算而不是21个单元运算呢?
最佳答案
不不不,你误解了这个想法。这个想法是对流的惰性评估。两者都需要“8 次计算”(用他的话说),他试图说看起来需要 21 次。
这个
numbers.stream()
.filter(MainClass::isGT3)
.filter(MainClass::isEven)
.map(MainClass::doubleIt)
.findFirst()
.orElse(0)
和
numbers.stream()
.filter(e -> e > 3)
.filter(e -> e % 2 == 0)
.map(e -> e * 2)
.findFirst()
.orElse(0)
完全相同。唯一的区别是创建一个更具可读性的函数,仅此而已。 命令式代码:
List<Integer> numbers = Arrays.asList(1, 2, 3, 5, 4, 6, 7, 8, 9, 10);
int result = 0;
for(int e: values){
if(e > 3 && e % 2 == 0){
result = e * 2;
break;
}
}
和流中的代码,计算完全相同,因为它们是按需调用的,这意味着它不会过滤所有 > 3
和过滤所有 % 2 == 0
,不,它结合了这些操作,然后在调用终端函数时应用它(如 findFirst()
)
如视频所示,如果您在函数之间放置一些印记,它将显示 8 个操作:
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 5, 4, 6, 7, 8, 9, 10);
System.out.println(processStream(numbers));
System.out.println(getNumber(numbers));
System.out.println(getNumberEfficient(numbers));
}
static Stream<Integer> processStream(List<Integer> numbers){
return numbers.stream()
.filter(e -> {
System.out.println("GT3: " + e);
return e > 3;
})
.filter(e -> {
System.out.println("is Even: " + e);
return e % 2 == 0;
})
.map(e -> {
System.out.println("times 2: " + e);
return e * 2;
} );
}
static int getNumberEfficient(List<Integer> numbers){
return numbers.stream()
.filter(e -> {
System.out.println("GT3 and even: " + e);
return e > 3 && e % 2 == 0;
})
.map(e -> {
System.out.println("times 2: " + e);
return e * 2;
} )
.findFirst()
.orElse(0);
}
static int getNumber(List<Integer> numbers){
return numbers.stream()
.filter(e -> {
System.out.println("GT3: " + e);
return e > 3;
})
.filter(e -> {
System.out.println("is Even: " + e);
return e % 2 == 0;
})
.map(e -> {
System.out.println("times 2: " + e);
return e * 2;
} )
.findFirst()
.orElse(0);
}
}
它将返回:
This is the pipeline, nothing was executed, because is laze
java.util.stream.ReferencePipeline$3@7ba4f24f
Thees are the 8 operations:
GT3: 1
GT3: 2
GT3: 3
GT3: 5
is Even: 5
GT3: 4
is Even: 4
times 2: 4
8
And this is a little optimization, instead of doing two filters, you can do only one, and reduce from 8 to 6:
GT3 and even: 1
GT3 and even: 2
GT3 and even: 3
GT3 and even: 5
GT3 and even: 4
times 2: 4
8
关于整个列表上的 Java 8 流计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57264756/