MST

星途 面试题库

面试题:Java Stream复杂场景下终止操作触发的时机探讨

假设有一个包含大量自定义对象的Stream,对其进行一系列的中间操作(如filter、map等)后,使用findFirst()作为终止操作。在并行流和顺序流两种情况下,终止操作触发时,之前的中间操作执行过程有何不同?如何通过代码验证你的观点。
17.6万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

并行流和顺序流中间操作执行过程的不同

  1. 顺序流
    • 顺序流的中间操作是按照元素在Stream中的顺序依次执行的。例如,先执行filter操作,一个元素接一个元素地判断是否满足过滤条件,只有满足条件的元素才会进入后续的map等操作。每个元素的处理是顺序进行的,前一个元素处理完后才处理下一个元素。
  2. 并行流
    • 并行流会将流中的元素分成多个部分,然后使用多个线程并行地处理这些部分。对于filter操作,不同的线程会同时处理不同部分的元素进行过滤。但是,由于并行处理,元素的处理顺序是不确定的。而且,在并行流中,为了保证结果的正确性,一些中间操作可能需要额外的协调和合并步骤,比如在进行map操作后,需要将各个线程处理的结果合并起来。

代码验证

以下是使用Java 8 Stream API进行验证的代码示例:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

class CustomObject {
    private int id;

    public CustomObject(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }
}

public class StreamExecutionExample {
    public static void main(String[] args) {
        List<CustomObject> customObjectList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            customObjectList.add(new CustomObject(i));
        }

        // 顺序流
        System.out.println("顺序流:");
        customObjectList.stream()
               .filter(obj -> {
                    System.out.println("顺序流过滤: " + obj.getId());
                    return obj.getId() % 2 == 0;
                })
               .map(obj -> {
                    System.out.println("顺序流映射: " + obj.getId());
                    return obj.getId() * 2;
                })
               .findFirst()
               .ifPresent(System.out::println);

        // 并行流
        System.out.println("\n并行流:");
        customObjectList.parallelStream()
               .filter(obj -> {
                    System.out.println("并行流过滤: " + obj.getId());
                    return obj.getId() % 2 == 0;
                })
               .map(obj -> {
                    System.out.println("并行流映射: " + obj.getId());
                    return obj.getId() * 2;
                })
               .findFirst()
               .ifPresent(System.out::println);
    }
}

在上述代码中,我们创建了一个包含CustomObject的列表,并分别对其顺序流和并行流进行filtermap操作,同时在每个中间操作中打印日志,观察执行顺序。顺序流中日志打印的顺序和元素顺序一致,而并行流中日志打印顺序混乱,体现了并行处理的特性。