Java 8流计算在整个列表上

mah*_*454 3 java stream java-8 java-stream

我在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;
  }
}  
Run Code Online (Sandbox Code Playgroud)

有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)
        );


    }
}
Run Code Online (Sandbox Code Playgroud)

该代码看起来像有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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我真的想了解,如何证明它具有8个单元操作而不是21个单元操作?

Dam*_*ero 5

不不不,你误解了这个主意。这个想法是对流的惰性评估。两者都用“ 8个计算”(用他的话),他试图说看起来像21。

这个

  numbers.stream()
                  .filter(MainClass::isGT3)
                  .filter(MainClass::isEven)
                  .map(MainClass::doubleIt)
                  .findFirst()
                  .orElse(0)
Run Code Online (Sandbox Code Playgroud)

numbers.stream()
                .filter(e -> e > 3)
                .filter(e -> e % 2 == 0)
                .map(e -> e * 2)
                .findFirst()
                .orElse(0)
Run Code Online (Sandbox Code Playgroud)

一模一样的。唯一的区别是创建一个更具可读性的函数,仅此而已。命令代码:

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

并且流中的代码的计算方式完全相同,因为它们是按需调用的,这意味着它不会全部> 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

它会返回:

这是管道,什么也没执行,因为很懒

java.util.stream.ReferencePipeline$3@7ba4f24f
Run Code Online (Sandbox Code Playgroud)

Thees是8个操作:

GT3: 1
GT3: 2
GT3: 3
GT3: 5
is Even: 5
GT3: 4
is Even: 4
times 2: 4
8
Run Code Online (Sandbox Code Playgroud)

而且这是一个优化,而不是做两个过滤器,您只能做一个,然后从8减少到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
Run Code Online (Sandbox Code Playgroud)