How to Get the Last Element of a Stream in Java? – 如何在Java中获取一个流的最后一个元素?

最后修改: 2017年 5月 31日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

The Java Stream API was the major feature of the Java 8 release. Streams represent lazily-evaluated sequences of objects and provide a rich, fluent, and monadic-like API.

Java Stream API是Java 8版本的主要特征。Streams表示对象的懒惰评价序列,并提供丰富、流畅和类似单体的API。

In this article, we will have a quick look into ways of getting the last element of a Stream. Keep in mind that due to the nature of streams, it’s not a natural operation. Always make sure that you’re not working with infinite Streams.

在这篇文章中,我们将快速了解获取流的最后一个元素的方法。请记住,由于流的性质,这不是一个自然的操作。一定要确保你不是在处理无限的Streams.

2. Using the Reduce API

2.使用Reduce API

Reduce, simply put, reduces the set of elements in a Stream to a single element.

Reduce,简单地说,将Stream中的元素集合减少到一个单一元素。

In this case, we’ll reduce the set of elements to get the last element fn the Stream. Keep in mind that this method will only return deterministic results for sequential Streams.

在这种情况下,我们将减少元素的集合,以获得最后一个元素fn的Stream。请记住,这个方法只对连续的Streams返回确定性的结果。

Let’s use a List of String values, get the Stream from the List and then reduce:

让我们使用一个ListString值,从List中获得Stream,然后进行缩减。

List<String> valueList = new ArrayList<>();
valueList.add("Joe");
valueList.add("John");
valueList.add("Sean");

Stream<String> stream = valueList.stream();
stream.reduce((first, second) -> second)
  .orElse(null);

Here, the stream is reduced to a level where it is left with only the last element. If the stream is empty it will return a null value.

这里,流被减少到只剩下最后一个元素的程度。如果流是空的,它将返回一个null值。

2. Using the Skip Function

2.使用跳过功能

The other way to get the last element of the stream is by skipping all the elements before it. This can be achieved using Skip function of Stream class. Keep in mind that in this case, we are consuming the Stream twice so there is some clear performance impact.

获得流的最后一个元素的另一种方法是跳过它之前的所有元素。这可以通过Stream类的Skip函数来实现。请记住,在这种情况下,我们要消耗Stream两次,所以会有一些明显的性能影响

Let’s create a List of string values and use its size function to determine how many elements to skip to reach the last element.

让我们创建一个字符串值的List,并使用其size函数来确定要跳过多少个元素才能到达最后一个元素。

Here is the example code getting the last element using skip:

下面是使用skip获得最后一个元素的示例代码。

List<String> valueList = new ArrayList<String>();
valueList.add("Joe");
valueList.add("John");
valueList.add("Sean");

long count = valueList.stream().count();
Stream<String> stream = valueList.stream();
   
stream.skip(count - 1).findFirst().get();

“Sean” ends up being the last element.

“Sean”最终成为最后一个元素。

4. Getting the Last Element of an Infinite Stream

4.获得无限流的最后一个元素

Trying to get the last element of the infinite stream would lead to an infinite sequence of evaluation performed on infinite elements. Both skip and reduce will not come back from the execution of evaluation unless we limit the infinite stream to a specific number of elements using limit operation.

试图获取无限流的最后一个元素将导致对无限元素执行的无限序列的评估。除非我们使用limit操作将无限流限制在特定数量的元素中,否则skipreduce都不会从执行评估中回来。

Here is the example code where we took an infinite stream and tried to get the last element:

下面是一个例子的代码,我们采取了一个无限的流,并试图获得最后的元素。

Stream<Integer> stream = Stream.iterate(0, i -> i + 1);
stream.reduce((first, second) -> second).orElse(null);

Consequently, the stream will not come back from the evaluation and it will end up halting the execution of the program.

因此,流不会从评估中回来,它最终会停止程序的执行

5. Conclusion

5.总结

We saw different ways of getting the last element of a Stream both using reduce and Skip APIs. We also looked into why this is not possible with infinite streams.

我们看到了使用reduceSkip API获得Stream中最后一个元素的不同方法。我们还研究了为什么这在无限流中是不可能的。

We saw that getting the last element from a Stream is not easy in comparison to fetching it from other data structures. This is because of the lazy nature of Streams which are not evaluated unless the terminal function is invoked and we never know if the currently evaluated element is the last one.

我们看到,从Stream中获取最后一个元素与从其他数据结构中获取元素相比并不容易。这是因为Streams的懒惰特性,除非调用终端函数,否则不会被评估,我们永远不知道当前评估的元素是否是最后一个。

Code snippets can be found over on GitHub.

代码片段可以在GitHub上找到over。