MST
星途 面试题库

面试题:Java中Stream函数式接口延迟执行特性的体现

请解释Java Stream中函数式接口的延迟执行特性,并举例说明在哪些场景下这种特性会带来性能提升。
39.6万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

Java Stream中函数式接口的延迟执行特性

Java Stream的函数式接口(如filtermap等)的延迟执行特性指的是,这些操作并不会立即执行,而是等到一个终端操作(如collectforEach等)被调用时才会真正执行。这意味着在中间操作(函数式接口相关操作)被调用时,Stream只是记录下要执行的操作,而不会马上处理数据。这样做可以优化操作流程,避免不必要的计算。

性能提升场景举例

  1. 减少不必要计算 假设有一个包含大量整数的列表,需要找出其中第一个大于100的数并将其翻倍。如果没有延迟执行特性,在filter操作时就会对所有元素进行过滤检查,即使找到符合条件的元素后还会继续检查剩余元素。而延迟执行可以在找到第一个符合条件的元素后就停止后续操作。
List<Integer> numbers = Arrays.asList(1, 50, 150, 200, 300);
Optional<Integer> result = numbers.stream()
  .filter(n -> {
        System.out.println("Filtering: " + n);
        return n > 100;
    })
  .findFirst()
  .map(n -> {
        System.out.println("Mapping: " + n);
        return n * 2;
    });
result.ifPresent(System.out::println);
// 输出:
// Filtering: 1
// Filtering: 50
// Filtering: 150
// Mapping: 150
// 300

在上述代码中,filtermap操作都是延迟执行的,当findFirst终端操作被调用时,Stream从列表开始处理元素,找到第一个大于100的元素150后,就停止对剩余元素的过滤检查,直接执行map操作。

  1. 优化复杂操作链 当有多个中间操作组成的复杂操作链时,延迟执行可以对整个操作链进行优化。例如,对一个大文件的文本行进行处理,先过滤掉空行,再转换为大写,最后统计行数。
Path path = Paths.get("largeFile.txt");
try (Stream<String> lines = Files.lines(path)) {
    long count = lines
      .filter(line ->!line.isEmpty())
      .map(String::toUpperCase)
      .count();
    System.out.println("Non - empty lines count: " + count);
} catch (IOException e) {
    e.printStackTrace();
}

这里filtermap操作都是延迟执行,Stream可以在count终端操作调用时,以更高效的方式处理文件,而不是对每一行先进行过滤再进行转换,可能会减少内存占用和磁盘I/O操作。