Get last element of Stream/List in a one-liner(在单行中获取 Stream/List 的最后一个元素)
问题描述
如何在以下代码中获取流或列表的最后一个元素?
How can I get the last element of a stream or list in the following code?
其中 data.careas
是 List
:
CArea first = data.careas.stream()
.filter(c -> c.bbox.orientationHorizontal).findFirst().get();
CArea last = data.careas.stream()
.filter(c -> c.bbox.orientationHorizontal)
.collect(Collectors.toList()).; //how to?
正如您所见,使用特定的 filter
获取第一个元素并不难.
As you can see getting the first element, with a certain filter
, is not hard.
但是,在单行中获取最后一个元素确实很痛苦:
However getting the last element in a one-liner is a real pain:
- 我似乎无法直接从
Stream
获取它.(这只对有限的流有意义) - 你似乎也无法从
List
接口中获取first()
和last()
之类的东西,这真的很痛苦.
- It seems I cannot obtain it directly from a
Stream
. (It would only make sense for finite streams) - It also seems that you cannot get things like
first()
andlast()
from theList
interface, which is really a pain.
我没有看到在 List
接口中不提供 first()
和 last()
方法作为元素的任何论据在那里,是有序的,而且大小是已知的.
I do not see any argument for not providing a first()
and last()
method in the List
interface, as the elements in there, are ordered, and moreover the size is known.
但根据原始答案:如何获取有限 Stream
的最后一个元素?
But as per the original answer: How to get the last element of a finite Stream
?
就个人而言,这是我能得到的最接近的:
Personally, this is the closest I could get:
int lastIndex = data.careas.stream()
.filter(c -> c.bbox.orientationHorizontal)
.mapToInt(c -> data.careas.indexOf(c)).max().getAsInt();
CArea last = data.careas.get(lastIndex);
但是它确实涉及在每个元素上使用 indexOf
,这很可能不是您通常想要的,因为它会影响性能.
However it does involve, using an indexOf
on every element, which is most likely not you generally want as it can impair performance.
推荐答案
可以通过Stream::reduce.以下清单包含一般情况的最小示例:
It is possible to get the last element with the method Stream::reduce. The following listing contains a minimal example for the general case:
Stream<T> stream = ...; // sequential or parallel stream
Optional<T> last = stream.reduce((first, second) -> second);
此实现适用于所有 有序流(包括从 列表创建的流).对于 无序 流出于明显的原因,未指定将返回哪个元素.
This implementations works for all ordered streams (including streams created from Lists). For unordered streams it is for obvious reasons unspecified which element will be returned.
该实现适用于顺序和并行流.乍一看,这可能令人惊讶,不幸的是,文档没有明确说明.但是,它是流的一个重要特性,我试图澄清它:
The implementation works for both sequential and parallel streams. That might be surprising at first glance, and unfortunately the documentation doesn't state it explicitly. However, it is an important feature of streams, and I try to clarify it:
- Stream::reduce 声明,它"不受限制顺序执行".
- Javadoc 还要求 " 累加器函数必须是 关联、无干扰、无状态函数,以便将两个values",这显然是 lambda 表达式
(first, second) -> 的情况.第二个
. - reduction 的 Javadoc操作 声明:流类有多种形式的通用归约操作,称为 reduce() 和 collect() [..]" 和 "只要用于处理元素的函数是 associative 和 无状态."
- The Javadoc for the method Stream::reduce states, that it "is not constrained to execute sequentially".
- The Javadoc also requires that the "accumulator function must be an associative, non-interfering, stateless function for combining two values", which is obviously the case for the lambda expression
(first, second) -> second
. - The Javadoc for reduction operations states: "The streams classes have multiple forms of general reduction operations, called reduce() and collect() [..]" and "a properly constructed reduce operation is inherently parallelizable, so long as the function(s) used to process the elements are associative and stateless."
密切相关的文档 收集器 更加明确:为确保顺序和并行执行产生等效结果,收集器函数必须满足身份和 关联性 约束."
The documentation for the closely related Collectors is even more explicit: "To ensure that sequential and parallel executions produce equivalent results, the collector functions must satisfy an identity and an associativity constraints."
回到原来的问题:下面的代码在变量last
中存储了对最后一个元素的引用,如果流为空则抛出异常.复杂度与流的长度成线性关系.
Back to the original question: The following code stores a reference to the last element in the variable last
and throws an exception if the stream is empty. The complexity is linear in the length of the stream.
CArea last = data.careas
.stream()
.filter(c -> c.bbox.orientationHorizontal)
.reduce((first, second) -> second).get();
这篇关于在单行中获取 Stream/List 的最后一个元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:在单行中获取 Stream/List 的最后一个元素
基础教程推荐
- 无法使用修饰符“public final"访问 java.util.Ha 2022-01-01
- 降序排序:Java Map 2022-01-01
- 在 Libgdx 中处理屏幕的正确方法 2022-01-01
- Java Keytool 导入证书后出错,"keytool error: java.io.FileNotFoundException &拒绝访问" 2022-01-01
- 设置 bean 时出现 Nullpointerexception 2022-01-01
- 减少 JVM 暂停时间 >1 秒使用 UseConcMarkSweepGC 2022-01-01
- 如何使用 Java 创建 X509 证书? 2022-01-01
- “未找到匹配项"使用 matcher 的 group 方法时 2022-01-01
- FirebaseListAdapter 不推送聊天应用程序的单个项目 - Firebase-Ui 3.1 2022-01-01
- Java:带有char数组的println给出乱码 2022-01-01