如何在以下代码中获取流或列表的最后一个元素?
其中 data.careas
是一个 List<CArea>
:
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
获取第一个元素并不难。
然而,获取单行中的最后一个元素是一个真正的痛苦:
- 看来我无法直接从
Stream
获得它。 (这只对有限流有意义) - 似乎您也无法从
List
界面获得诸如first()
和last()
之类的东西,这真的很痛苦。
我没有看到任何关于不提供 first()
和 last()
方法的 List
接口中的方法和更多的元素,如众所周知。
但根据原始答案:How to get the last element of a finite Stream
?
就个人而言,这是我能得到的最接近的:
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
,这很可能不是您通常想要的,因为它会影响性能。
原文由 skiwi 发布,翻译遵循 CC BY-SA 4.0 许可协议
可以使用 Stream::reduce 方法获取最后一个元素。以下清单包含一般情况的最小示例:
此实现适用于所有 有序流(包括从 Lists 创建的流)。对于 无序 流,由于显而易见的原因,未指定将返回哪个元素。
该实现适用于 顺序 流和 并行流。乍一看这可能令人惊讶,不幸的是文档没有明确说明。然而,它是流的一个重要特性,我试着澄清一下:
(first, second) -> second
的情况。密切相关的 收集器 的文档更加明确: “为了确保 顺序 执行和 并行执行 产生 相同的结果,收集器函数必须满足身份和 关联性 约束。”
回到最初的问题:下面的代码存储了对变量中最后一个元素的引用
last
,如果流为空则抛出异常。复杂度与流的长度成线性关系。