1. 概述
在这个简短的教程中,我们将快速了解Java流中的中级和终止操作,创建空流的方法,以及如何检查空流。
2. 流与流操作
Java 8的特性之一是流(Stream)API。流是一系列元素,我们可以对其进行迭代并执行操作。
流操作主要分为两种类型——中级和终端。 中级和终端操作可以串联在一起形成流管道。
终端操作顾名思义,位于流管道的末尾,返回结果,如distinct()
,或产生副作用,如forEach()
。
另一方面,中级操作如sorted()
会将流转换为另一个流。因此,我们可以链式多个中级操作。
任何终端或中级操作都不会实际改变流的源头,而是产生结果。 同时,中级操作以懒惰的方式进行,只有在启动终端操作后才会执行计算。
让我们看一个例子:
Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5, 6);
int sumOfEvenNumbers = numbers
.filter(number -> number%2 == 0)
.reduce(0, Integer::sum);
Assert.assertEquals(sumOfEvenNumbers, 12);
这里我们创建了一个整数流。我们使用了中级操作filter()
,它创建了一个偶数流。最后,我们使用了终端操作reduce()
来获取所有偶数的总和。
3. 在Java中创建空流
有时,我们可能需要将流作为参数传递给方法,或者从方法返回流。空流对于处理NullPointerException
很有用。 此外,一些流操作,如findFirst()
, findAny()
, min()
, 和 max()
,会在检查流是否为空后返回相应结果。
创建流有多种方式,因此创建空流的方法也有多样性。
首先,我们可以直接使用Stream
类的empty()
方法:
Stream<String> emptyStream = Stream.empty();
empty()
方法返回一个空的顺序字符串流。
我们也可以使用of()
方法创建任何类型的空流。of()
方法返回一个有序的序列流,包含传给它的参数作为元素。如果没有传入参数,它将返回一个空流:
Stream<String> emptyStr = Stream.of();
同样,我们可以使用IntStream
创建基本类型的流:
IntStream intStream = IntStream.of(new int[]{});
Arrays
类有一个方法stream()
,接受数组作为参数并返回与参数类型相同的流。我们可以使用这个方法通过传入一个空数组来创建一个空流:
IntStream emptyIntStream = Arrays.stream(new int[]{});
最后,我们可以使用List
或Set
等集合的stream()
方法创建空流。空集合将创建一个空流:
Stream<Integer> emptyIntStream = new ArrayList<Integer>().stream();
4. 检查空流
我们可以通过使用诸如findFirst()
或findAny()
等短路终端操作来检查空流:
Stream<String> emptyStream = Stream.empty();
assertTrue(emptyStream.findAny().isEmpty());
这里,findFirst()
如果流为空则返回一个空的Optional
。然后我们检查Optional
中是否存在值。由于流为空,Optional
中没有值,它返回false
。
然而,我们必须记住,我们只能对流进行一次操作。如果我们重用流,可能会遇到IllegalStateException
:
IllegalStateException: stream has already been operated upon or closed.
因此,我们只允许执行消耗流的操作一次。如果我们想重用流,必须处理这个IllegalStateException
。
为了解决这个问题,每当需要检查流是否为空时,我们可以使用Supplier
函数接口创建一个新的流:
Supplier<Stream<Integer>> streamSupplier = Stream::of;
Optional<Integer> result1 = streamSupplier.get().findAny();
assertTrue(result1.isEmpty());
Optional<Integer> result2 = streamSupplier.get().findFirst();
assertTrue(result2.isEmpty());
在这里,我们首先定义了一个空流,然后创建了一个streamSupplier
对象,类型为Stream<Integer>
。这样,每次调用get()
方法都会返回一个新的空流对象,我们可以安全地在其上执行另一个流操作。
5. 总结
在这篇简短的文章中,我们了解了一些在Java中创建空流的方法。我们还探索了如何检查流是否为空,以及如何在避免因流已关闭或已被操作而抛出的著名IllegalStateException
的情况下多次重用流。
如往常一样,本文的源代码可以在GitHub上找到。