欢迎访问宙启技术站
智能推送

Java中的Stream函数-流式操作简介

发布时间:2023-06-12 20:53:32

Java 8 引入了 Stream API,它是一种新的用于处理数据的函数式编程方式。Stream API 的设计就是为了让开发者能够更加容易地对集合进行操作。Stream API 是通过对集合进行不同的过滤、排序、映射等操作来处理数据的。

Stream API 的一个重要的特点就是流式操作,这种操作方式可以使得代码更加简洁、易于理解,并且可以提高代码的复用性。这篇文章将会介绍 Stream 函数式编程机制以及其提供的流式操作。

## Stream API

Stream API 是 Java 8 提供的一个流式操作框架,它允许开发者使用函数式编程的方式来处理大量的数据。Stream API 的主要特点包括:

1. 支持链式编程,使代码更加简洁、易于理解;

2. 提供了像 SQL 语句一样的 API,方便开发者进行数据查询;

3. 支持多线程并发执行操作;

4. 支持串行和并行两种方式对数据进行操作。

Stream API 由三个部分构成:流、中间操作和终止操作。

![Stream API](https://img-blog.csdn.net/20180529164014405?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2FhZGhh/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/q/50)

1. 流:Stream 是元素的序列,它的来源可以是一个集合、数组、文件、网络资源,甚至是一个随机数生成器等。流管理了其自己的内部数据,而不是修改原始集合或数据源。

2. 中间操作:所有中间操作返回一个新的流,让流能够链接操作。比如 filter()、map()、sorted() 和 peek() 等。中间操作的重要特性就是延迟执行,它们只描述流的操作,不会立即执行。

3. 终止操作:终止操作是流的最后一环,它们执行中间操作链,并产生某个结果。比如 forEach()、count()、sum()、max() 和 min() 等。终止操作会从流中消费元素,它们是流操作的触发点。

## 中间操作

Stream API 提供了大量的中间操作,这里介绍一下其中比较常用的操作。

### filter() 过滤

filter() 方法可以接受一个 Predicate 接口类型的参数,用于对流中的元素进行过滤。该方法会返回一个新的 Stream,其中仅包含符合条件的元素。例如,以下代码演示了如何过滤集合中的元素:

List<String> names = Arrays.asList("taobao", "tianmao", "jingdong", "suning");
Stream<String> filteredStream = names.stream().filter(name -> name.length() > 6);

上面的代码中,我们通过调用 names 集合的 stream() 方法来获取一个流,然后再调用 filter() 方法对流进行过滤。在 filter() 方法中,我们传入了一个 Lambda 表达式,该表达式实现了 Predicate 接口中的 test() 方法。这个 Lambda 表达式的作用是筛选出字符串长度大于 6 的元素。

### map() 映射

map() 方法用于对元素进行映射操作,返回由映射后的元素组成的新流。map() 方法可以接受一个 Function 接口类型的参数,用于对流中的每一个元素进行转换或者操作。例如,以下代码演示了如何将集合中的所有元素转换为大写字母:

List<String> names = Arrays.asList("taobao", "tianmao", "jingdong", "suning");
Stream<String> mappedStream = names.stream().map(String::toUpperCase);

上面的代码中,我们首先调用 names 集合的 stream() 方法获取一个流,然后再调用 map() 方法对流的元素进行映射。在 map() 方法中,我们传入了静态引用 String::toUpperCase,它会将每个字符串转换为大写字母。

### sorted() 排序

sorted() 方法用于排序流中的元素。它可以接受 Comparator 接口类型的参数,用于指定排序规则。如果不传入任何参数,则默认使用自然排序规则。例如,以下代码演示了如何对数字流进行升序排列:

List<Integer> nums = Arrays.asList(3, 6, 2, 1, 7, 4, 5);
Stream<Integer> sortedStream = nums.stream().sorted();

上面的代码中,我们首先调用 nums 集合的 stream() 方法获取一个流,然后再调用 sorted() 方法对流的元素进行排序。由于没有传入任何参数,所以默认使用自然排序规则。

### limit() 截取

limit() 方法用于截取流中的前 n 个元素,返回一个新的流。如果流的长度小于 n,则返回原始流。例如,以下代码演示了如何截取数字流中的前 3 个元素:

List<Integer> nums = Arrays.asList(3, 6, 2, 1, 7, 4, 5);
Stream<Integer> limitedStream = nums.stream().limit(3);

上面的代码中,我们首先调用 nums 集合的 stream() 方法获取一个流,然后再调用 limit() 方法对流进行截取,返回一个包含前 3 个元素的新流。

## 终止操作

Stream API 提供了大量的终止操作,用于触发中间操作链,并产生某个结果。这里介绍一下其中比较常用的操作。

### forEach() 遍历

forEach() 方法用于对流中的每一个元素进行迭代操作。它接受一个 Consumer 接口类型的参数,用于对每个元素进行操作。例如,以下代码演示了如何遍历数字流中的所有元素:

List<Integer> nums = Arrays.asList(3, 6, 2, 1, 7, 4, 5);
nums.stream().forEach(System.out::println);

上面的代码中,我们首先调用 nums 集合的 stream() 方法获取一个流,然后再调用 forEach() 方法对流中的每一个元素进行操作。在 forEach() 方法中,我们传入了静态引用 System.out::println,它会将每个元素输出到控制台。

### count() 计数

count() 方法用于对流中的元素进行计数操作。它返回一个 long 类型的值,表示流中元素的数量。例如,以下代码演示了如何计算数字流中的元素个数:

List<Integer> nums = Arrays.asList(3, 6, 2, 1, 7, 4, 5);
long count = nums.stream().count();
System.out.println(count);

上面的代码中,我们首先调用 nums 集合的 stream() 方法获取一个流,然后再调用 count() 方法对流中的元素进行计数操作。该方法会返回一个 long 类型的值,表示流中元素的数量。

### reduce() 聚合

reduce() 方法用于对流中的元素进行聚合操作,返回一个 Optional 类型的值。它接受一个 BinaryOperator 接口类型的参数,用于指定聚合规则。例如,以下代码演示了如何对数字流进行求和操作:

List<Integer> nums = Arrays.asList(3, 6, 2, 1, 7, 4, 5);
Optional<Integer> sum = nums.stream().reduce((x, y) -> x + y);
System.out.println(sum.get());

上面