以单线forms获取Stream / List的最后一个元素
如何获得下面的代码中的stream或列表的最后一个元素?
where 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
获取它。 (这只对有限的stream才有意义) - 也似乎你不能从
List
接口得到first()
和last()
这样的东西,这真的很痛苦。
我没有看到在List
接口中没有提供first()
和last()
方法的任何参数,因为那里的元素是有序的,而且大小是已知的。
但按照原来的答案:如何获得有限的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
,这很可能不是您通常想要的,因为它可能会影响性能。
使用Stream :: reduce方法可以得到最后一个元素。 以下列表包含一般情况的一个简单示例:
Stream<T> stream = ...; // sequential or parallel stream Optional<T> last = stream.reduce((first, second) -> second);
这个实现适用于所有有序的stream (包括从列表创build的stream)。 对于无序的stream,没有指定哪个元素将被返回是显而易见的原因。
该实现适用于顺序 stream和并行stream 。 乍一看,这可能会令人惊讶,不幸的是,文件没有明确说明。 但是,这是stream的重要特征,我试图澄清它:
- 方法Stream :: reduce状态的Javadoc,它“ 不受限于顺序执行” 。
- Javadoc还要求“累加器函数必须是结合两个值的关联 , 无干扰 , 无状态函数” ,这对于lambdaexpression式
(first, second) -> second
显然是这种情况。 - 用于约简操作的Javadoc指出: “stream类具有多种forms的通用约简操作,称为reduce()和collect() [..]”,并且“适当构造的约 简操作 本质上是可并行化的 ,只要函数)用来处理元素是联想和无状态的 。“
密切相关的收集器的文档更加明确: “为了确保顺序 执行和并行执行产生相同的结果 ,收集器函数必须满足标识和关联约束。
回到原来的问题:下面的代码存储对最后一个variables元素的引用,如果stream为空,则引发exception。 stream的长度的复杂性是线性的。
CArea last = data.careas.stream() .filter(c -> c.bbox.orientationHorizontal) .reduce((first, second) -> second).get();
如果你有一个Collection(或者更一般的Iterable),你可以使用Google Guava的
Iterables.getLast(myIterable)
作为方便的在线。
一个class轮(不需要stream);
Object lastElement = list.get(list.size()-1);
由于目前还不清楚它是否是API规范的一部分,以reduce
服从碰撞命令,那么:
CArea last = data.careas.stream() .filter(c -> c.bbox.orientationHorizontal) .max((e1, e2) -> data.careas.indexOf(e1) - data.careas.indexOf(e2)).get();
正如@nosid提到的那样,可以使用reduce来完成。 这样做的另一种方法是倒转stream,然后得到第一个元素
CArea last = data.careas.stream() .filter(c -> c.bbox.orientationHorizontal) .sorted((a, b)-> -1) .findFirst().get();
您可以使用以下静态方法使用java.util.Collections
:
Collections.max(yourList);
从文档:
根据元素的自然sorting ,返回给定集合的最大元素。 […]