首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在一行程序中获取Stream/List的最后一个元素

在一行程序中获取Stream/List的最后一个元素
EN

Stack Overflow用户
提问于 2014-01-29 17:25:07
回答 6查看 113.7K关注 0票数 141

如何在下面的代码中获取流或列表的最后一个元素?

在哪里data.careas

是一个List

代码语言:javascript
复制
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

..。(它只对有限的流有意义)

看起来你也不能得到像这样的东西first()

last()

List

接口,这真的很痛苦。

我看不出有任何理由不提供first()

last()

方法中的List

接口中的元素是有序的,而且大小是已知的。

但根据最初的答案:如何获取有限元的最后一个元素

就我个人而言,这是我能得到的最接近的结果:

代码语言:javascript
复制
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

在每个元素上,这很可能不是您通常想要的,因为它可能会影响性能。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2014-01-30 04:13:05

可以使用方法获取最后一个元素流Stream::reduce.下面的清单包含一般情况的最小示例:

代码语言:javascript
复制
Stream stream = ...; // sequential or parallel stream
Optional last = stream.reduce((first, second) -> second);

此实现适用于所有人ordered streams(包括从以下位置创建的Lists)。对于unorderedstreams由于明显的原因,未指定将返回哪个元素。该实现对这两种情况都有效。顺序和并行流。乍一看,这可能会令人惊讶,但不幸的是,文档并没有明确说明这一点。然而,这是streams的一个重要特性,我试着澄清一下:

Stream::reduce方法的 Javadoc 指出,它“不受限于顺序执行”。 Javadoc 还要求“累加器函数必须是用于组合两个值的关联的、无干扰的、无状态的函数”,这显然是 lambda 表达式 (first, second) -> second 的情况。reduction operations Javadoc 声明:“流类有多种形式的通用归约操作,称为 reduce()

collect() [..]”和“一个正确构造的归约操作本质上是可并行化的,只要函数) 用于处理元素是的associativestateless."的。

” 密切相关Collectors的文档更加明确:“为了确保顺序和并行执行产生等效的结果,收集器函数必须满足associativity和关联性约束。”

回到最初的问题:下面的代码在变量 last中存储了对最后一个元素的引用,如果流为空则抛出异常。复杂度与流的长度呈线性关系。

代码语言:javascript
复制
CArea last = data.careas
                 .stream()
                 .filter(c -> c.bbox.orientationHorizontal)
                 .reduce((first, second) -> second).get();
票数 223
EN

Stack Overflow用户

发布于 2015-10-07 15:34:54

如果你有一个Collection (或者更通用的Iterable),你可以使用Google Guava

代码语言:javascript
复制
Iterables.getLast(myIterable)

就像一个很好用的眼线笔。

票数 49
EN

Stack Overflow用户

发布于 2019-05-08 02:24:36

对于这种情况,Guava有专门的方法:

代码语言:javascript
复制
Stream stream = ...;
Optional lastItem = Streams.findLast(stream);

它相当于stream.reduce((a, b) -> b)但创建者声称它的性能要好得多。

From documentation:

来自文档此方法的运行时间将介于O(log )和O(n)之间,在高效可拆分的流上执行得更好。

值得一提的是,如果流是无序的,则此方法的行为类似于findAny()

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21426843

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档