reduce 到底是什么?Java8 Stream 的终极聚合工具详解

reduce() 是 Java Stream API 提供的一个终端操作方法,用于将流中的元素组合起来生成一个单一的值。这一方法非常强大,可以实现累积、聚合、拼接等功能,适用于各种数据处理场景。


1. reduce() 方法的作用

reduce() 是一个通用的归约操作,它通过一个 关联函数,逐个处理流中的每个元素,将其累积为一个值。
方法签名如下:

无初始值的 reduce

Optional reduce(BinaryOperator accumulator);

带初始值的 reduce

T reduce(T identity, BinaryOperator accumulator);

带初始值且支持并行计算的 reduce

 U reduce(U identity, BiFunction accumulator, BinaryOperator combiner);

2. reduce() 的参数详解

  1. identity (初始值)

    • 归约过程的起始值。
    • 如果流为空,则直接返回此初始值。
  2. accumulator (累加器)

    • 一个函数,定义了如何将流中的元素与当前累积值结合。
  3. combiner (组合器)

    • 仅在并行流中使用,定义了如何将多个部分结果合并成一个结果。

3. 常见使用场景与示例

3.1 求和

通过 reduce() 实现流中所有元素的求和。

import java.util.Arrays;
import java.util.List;

public class ReduceExample {
    public static void main(String[] args) {
        List numbers = Arrays.asList(1, 2, 3, 4, 5);

        // 使用 reduce 求和
        int sum = numbers.stream()
                .reduce(0, Integer::sum); // 初始值为 0,累加操作

        System.out.println("Sum: " + sum); // 输出 15
    }
}

3.2 求最大值

利用 reduce() 找出流中的最大值。

import java.util.Arrays;
import java.util.List;

public class MaxExample {
    public static void main(String[] args) {
        List numbers = Arrays.asList(7, 2, 8, 1, 4);

        // 使用 reduce 求最大值
        int max = numbers.stream()
                .reduce(Integer.MIN_VALUE, Integer::max);

        System.out.println("Max: " + max); // 输出 8
    }
}

3.3 字符串拼接

将流中的字符串拼接为一个完整的字符串。

import java.util.Arrays;
import java.util.List;

public class StringConcatenation {
    public static void main(String[] args) {
        List words = Arrays.asList("Java", "is", "fun");

        // 使用 reduce 拼接字符串
        String result = words.stream()
                .reduce("", (s1, s2) -> s1 + " " + s2);

        System.out.println("Concatenated String: " + result.trim()); // 输出 "Java is fun"
    }
}

3.4 计算乘积

通过 reduce() 实现乘积计算。

import java.util.Arrays;
import java.util.List;

public class ProductExample {
    public static void main(String[] args) {
        List numbers = Arrays.asList(1, 2, 3, 4);

        // 使用 reduce 计算乘积
        int product = numbers.stream()
                .reduce(1, (a, b) -> a * b);

        System.out.println("Product: " + product); // 输出 24
    }
}

4. Optional reduce() 的特殊处理

reduce() 方法没有初始值时,返回的是一个 Optional,因为流可能为空。开发者需要显式处理 Optional

示例

import java.util.Arrays;
import java.util.Optional;

public class OptionalReduce {
    public static void main(String[] args) {
        // 空流的情况
        Optional result = Arrays.asList().stream()
                .reduce((a, b) -> a + b);

        // 处理 Optional
        System.out.println(result.orElse(0)); // 如果为空,输出 0
    }
}

5. reduce() 的高级用法

5.1 使用 combiner 处理并行流

当使用并行流时,reduce() 的第三个参数 combiner 非常重要,它用于合并多个线程的部分结果。

import java.util.Arrays;
import java.util.List;

public class ParallelReduceExample {
    public static void main(String[] args) {
        List numbers = Arrays.asList(1, 2, 3, 4, 5);

        // 使用并行流和 combiner
        int sum = numbers.parallelStream()
                .reduce(0,
                        Integer::sum, // 累加器
                        Integer::sum  // 组合器
                );

        System.out.println("Sum using parallel stream: " + sum); // 输出 15
    }
}

5.2 统计单词长度

通过 reduce() 计算单词总长度。

import java.util.Arrays;
import java.util.List;

public class WordLengthExample {
    public static void main(String[] args) {
        List words = Arrays.asList("apple", "banana", "cherry");

        // 使用 reduce 统计总长度
        int totalLength = words.stream()
                .reduce(0,
                        (length, word) -> length + word.length(),
                        Integer::sum);

        System.out.println("Total length: " + totalLength); // 输出 17
    }
}

6. 小结

  1. 选择适当的初始值:有初始值的 reduce() 更安全,因为它不会返回 Optional
  2. 明确操作的数学意义reduce() 适合处理具有结合律和交换律的操作。
  3. 善用 combiner:在并行流中,combiner 能确保结果正确合并。
  4. 关注性能:对大流使用并行流的 reduce() 可以显著提升效率。

通过 reduce(),我们可以优雅地处理复杂的数据聚合需求,使代码更加简洁高效。

欢迎follow同名gzh: 加瓦点灯,每天推送干货知识,每天进步一点点!@@

本文由mdnice多平台发布

你可能感兴趣的:(程序员)