单行获取Stream / List的最后一个元素
如何在以下代码中获取流或列表的最后一个元素?
哪里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
。(仅对有限的流有意义) - 这似乎也不能得到像
first()
和last()
从List
接口,这实在是一种痛苦。
我看不到在接口中不提供first()
and last()
方法的任何参数List
,因为其中的元素是有序的,而且大小是已知的。
但是按照原始答案:如何获得有限的最后一个元素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
在每个元素上使用on,这通常是您通常不希望的,因为它会影响性能。
回答:
可以使用Stream ::
reduce方法获取最后一个元素。下面的清单包含一般情况的最小示例:
Stream<T> stream = ...; // sequential or parallel streamOptional<T> last = stream.reduce((first, second) -> second);
此实现适用于所有有序流(包括从List创建的流)。对于无序流,由于显而易见的原因,未指定将返回哪个元素。
该实现适用于 和
。乍一看这可能令人惊讶,但是不幸的是文档没有明确说明。但是,它是流的重要功能,我尝试对其进行澄清:
- 方法Stream :: reduce的Javadoc 指出,它 “ 执行的约束”。
- Javadoc还要求 “累加器函数必须是 用于组合两个值的 , , 函数”,这显然是lambda表达式的情况
(first, second) -> second
。 - 用于归约运算的Javadoc 指出: “流类具有多种形式的常规归约运算,分别称为 reduce()和collect() [..]”_和 “ 只要函数具有适当的构造,reduce运算就 性。 )用于处理元素是关联的和无状态的。”_
与密切相关的收集器的文档更加明确:
“为确保 和 产生
,收集器功能必须满足标识和关联性约束。”
回到原始问题:以下代码将对最后一个元素的引用存储在变量中last
,如果流为空,则引发异常。复杂度在流的长度上是线性的。
CArea last = data.careas .stream()
.filter(c -> c.bbox.orientationHorizontal)
.reduce((first, second) -> second).get();
以上是 单行获取Stream / List的最后一个元素 的全部内容, 来源链接: utcz.com/qa/434469.html