Java8 reduce操作详解
Java8 reduce操作详解
登录
Java8 reduce操作详解
Java8 reduce操作详解

Java8 reduce操作详解

什么是reduce

Java8 中有两大最为重要的改变,其一是 Lambda 表达式,另一个就是 Stream API 了。

Stream[] 是 Java8 中处理集合的[]关键抽象概念[],它将数据源[]流化后,可以[]执行非常复杂[]的查找、过滤[]和映射数据、[]排序、切片、[]聚合统计等操[]作。操作之后[]会产生一个新[]的流,而数据[]源则不会发生[]改变。

在使用 Stream 操作的过程中,往往有三个步骤,

1. 创建Stream

从一个数据源(集合,数组)中,新建一个 Stream 流。

2. 中间操作

一个中间操作链,对 Stream 流的数据进行处理。比如查找、过滤、映射转换等。

3. 终止操作

一个终止操作,执行中间操作链,并产生结果。常用的终止操作有 forearch、collect、match、count、min、max、reduce 等。

其中本文主要[]讲解的 reduct[] 操作就属于是[] Stream[] 流操作中的终[]止操作。

reduce[] 操作是一种通[]用的归约操作[],它可以实现[]从 Stream[] 中生成一个值[],其生成的值[]不是随意的,[]而是根据指定[]的计算模型。[]

比如终止操作[]中提到 count、[]min 和 max 方法,因为常[]用而被纳入标[]准库中。事实[]上这些方法都[]是一种 reduce[] 操作。

本文大纲如下,

Java8 reduce操作详解

reduce 操作三要素

为了方便大家理解 reduce (规约)操作,先给大家演示一下 reduce 操作的相关代码示例,

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);int result = numbers  .stream()  .reduce(0, (subtotal, element) -> subtotal + element);assertThat(result).isEqualTo(21);

可以看到,我们的 reduce 操作接受了三个参数,返回了一个 int 基本类型。

在 Stream API 中,提供了三个 reduct 操作方法,根据参数不同进行区分。

Java8 reduce操作详解

对应上方代码示例,也就是使用了接受两个参数的 reduce 方法,但其实接受两个参数的 reduce 方法的代码逻辑是和接受三个参数的 reduce 方法是一致的。通过上方截图可以看出。

所以这里,我就直接给大家介绍下 reduce 操作的三个参数分别有什么作用即可。

identiy 参数

identiy(初始值)是 reduce 操作的初始值,也就是当元素集合为空时的默认结果。对应上方代码示例,也就是说 reduce 操作的初始值是 0。

accumulator 参数

accumulator(累加器)是一个函数,它接受两个参数,reduce 操作的部分元素和元素集合中的下一个元素。它返回一个新的部分元素。在这个例子中,累加器是一个 lambda 表达式,它将集合中两个整数相加并返回一个整数:(a, b) -> a + b。

combiner 参数

combiner(组合器)是一个函数,它用于在 reduce 操作被并行化或者当累加器的参数类型和实现类型不匹配时,将 reduce 操作的部分结果进行组合。在上面代码示例中,我们不需要使用组合器,因为上面我们的 reduce 操作不需要并行,而且累加器的参数类型和实现类型都是 Integer。

为了方便大家理解 reduce 操作的内部逻辑,我给大家绘制了上面代码示例的执行示意图,如下,

Java8 reduce操作详解

如何使用 reduce 操作

为了更好地理解初始值,累加器和组合器的功能,让我们看一些基本的例子。

使用 reduce 查询整数集合的最小值

// 创建一个整数集合List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);// 找出集合中的最小值Integer min = numbers.stream().reduce((integer, integer2) -> {    if (integer < integer2) {        return integer;    } else {        return integer2;    }}).get();// 输出结果System.out.println(min); // 1

在这个例子中,我们使用了一个参数的 reduce 操作,它接受一个累加器函数。累加器函数会返回集合两个元素中,较小的元素。

最终我们就可以找出集合中最小值 1。

使用 reduce 操作拼接字符串列表

我们可以对一个字符串列表使用 reduce 操作,将它们拼接成一个单一的字符串:

// 创建一个字符串列表List<String> letters = Arrays.asList ("a", "b", "c", "d", "e");// 使用 reduce 操作拼接字符串列表String result = letters  .stream ()  .reduce ("", (partialString, element) -> partialString + element);// 输出结果System.out.println (result); // abcde

在这个例子中,我们将初始值设为 “”,累加器函数设为 (a, b) -> a + b,它表示将两个字符串拼接起来。

我们可以看到,reduce 操作将累加器函数反复应用到列表中的每个元素上,得到最终的结果 abcde。

使用并行流计算整数列表的总和

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5,6);// 使用并行流和 reduce() 方法计算整数列表的总和int result = numbers.parallelStream()        .reduce(0, (a, b) -> a + b, Integer::sum);// 输出结果System.out.println(result); // 21

在这个例子中,我们使用 parallelStream() 方法将列表转换为并行流,再使用 reduce() 方法对整数列表进行 reduce 操作,并使用 Integer::sum 作为合并函数 combiner,将并行计算的结果合并。

使用并行流的[]好处能够充分[]利用多核 CPU 的优势,使用[]多线程加快对[]集合数据的处[]理速度。

不过并行流也[]不是任何时候[]都可以使用的[],并行流执行[]过程中实际按[]照多线程执行[],多线程编程[]有的问题,并[]行流都有。

比如多线程的线程安全,执行顺序等问题,并行流都是有的。这一点需要大家注意。

最后聊两句

本文介绍了 Java8 Stream 流中,reduce 操作的相关概念和接收参数,包含初始值,累加器和组合器,最后介绍了 reduce 操作如何使用,希望大家喜欢。

    版权归属: noBug
    本文链接: https://wucuo.com/post/81
    相关推荐

    评论区

    评论头像