Java 8中中间操作和终端操作的区别

1. 概述

Java 8是Java语言的一个重要版本,它为开发者们带来了诸多革新。在Java 8中,引入了流(Stream)这个概念,它可以让我们更加方便地处理集合中的数据。在对集合中的数据进行处理时,通常将处理过程分为中间操作和终端操作两个部分。那么,这两个操作的区别是什么呢?

2. 中间操作和终端操作的含义

2.1 中间操作

中间操作,顾名思义,是对数据进行处理的过程中,涉及到的中间步骤。它们并不会立即执行,只有在终端操作调用之后才会执行。中间操作可以看做对原始集合数据的转换处理,转换出一个新的流。中间操作有:

过滤(Filter)

映射(Map)

排序(Sort)

去重(Distinct)

截取(Limit)

跳过(Skip)

2.2 终端操作

终端操作是对数据进行处理的最后一步,它们会触发中间操作进行计算,并且生成处理的结果。终端操作会产生一个新的数据结构或者一个副作用,而且它们只能被使用一次,不能重复使用。终端操作有:

遍历(ForEach)

计数(Count)

查找(Find)

归约(Reduce)

最大值(Max)

最小值(Min)

收集(Collect)

3. 中间操作和终端操作的区别

中间操作和终端操作在Java 8中都是返回一个流(Stream)类型。它们之间最主要的区别在于,当调用终端操作时,整个流才会被处理,并且不可以重新使用。而中间操作只是返回了一个新的流,而并不会对原来的流进行处理。下面通过几个示例来说明这种区别:

3.1 示例1:中间操作和终端操作的顺序

在下面的示例中,我们使用了中间操作map和终端操作forEach来对一个字符串进行转换,最后输出转换后的结果。

List list = Arrays.asList("a", "b", "c", "d", "e");

list.stream() // 创建流

.map(s -> s.toUpperCase()) // 转换为大写

.forEach(System.out::println); // 输出结果

可以看到,在这个示例中,我们先使用map方法对原始流进行了中间操作,然后使用forEach方法触发计算并输出结果。如果我们把这两个操作的顺序颠倒一下,会出现什么情况呢?

List list = Arrays.asList("a", "b", "c", "d", "e");

list.stream() // 创建流

.forEach(System.out::println) // 输出结果

.map(s -> s.toUpperCase()); // 转换为大写

这个代码片段会报错,提示void cannot be converted to java.util.stream.Stream

这是因为,forEach这个方法是一个终端操作,它返回的是void类型。如果在它之后再调用中间操作,会抛出一个编译时错误。

3.2 示例2:终端操作的延迟执行

在下面的示例中,我们依次使用了两个终端操作countfindFirst来对一个整数流进行计算。

List list = Arrays.asList(1, 2, 3, 4, 5);

long count = list.stream() // 创建流

.filter(i -> i > 2) // 过滤

.count(); // 统计符合要求的个数

System.out.println(count); // 输出结果

Optional opt = list.stream() // 创建流

.filter(i -> i > 2) // 过滤

.findFirst(); // 找到第一个符合要求的元素

System.out.println(opt.get()); // 输出结果

上面的代码中,首先我们使用count()方法计算符合条件的元素的个数,并将结果赋给count变量。然后我们又使用findFirst()方法找到第一个符合条件的元素,并将结果打印出来。

需要注意的是,如果我们在两个终端操作之间插入一个中间操作sorted(),会发生什么情况呢?

List list = Arrays.asList(1, 2, 3, 4, 5);

Optional opt = list.stream() // 创建流

.filter(i -> i > 2) // 过滤

.sorted() // 排序

.findFirst(); // 找到第一个符合要求的元素

System.out.println(opt.get()); // 输出结果

这段代码会抛出一个NoSuchElementException异常,表示没有找到符合要求的元素。究竟是为什么呢?这是因为sorted()方法对中间的数据进行排序,并返回一个新的流,但是该流中并没有符合要求的元素,因此在执行findFirst()方法时,无法找到符合条件的元素。这就是终端操作对中间操作的延迟执行。

4. 总结

本文介绍了Java 8中中间操作和终端操作的区别。虽然这两个操作都会返回一个流(Stream)类型,但是它们的最主要区别在于,当调用终端操作时,会触发中间操作进行处理,并且不可以重新使用。而中间操作只是返回一个新的流,对原来的流没有任何影响。

免责声明:本文来自互联网,本站所有信息(包括但不限于文字、视频、音频、数据及图表),不保证该信息的准确性、真实性、完整性、有效性、及时性、原创性等,版权归属于原作者,如无意侵犯媒体或个人知识产权,请来电或致函告之,本站将在第一时间处理。猿码集站发布此文目的在于促进信息交流,此文观点与本站立场无关,不承担任何责任。

后端开发标签