是否有一种理智的方式从列表中获取有序流(具体来说,数组列表,但它应该无关紧要)流式元素与它们在原始列表中的方式相反?
我需要在任何事物中缓冲数据(收集器,另一个列表,数组等,因为它们复制了浪费的容器),或使用 Collections.reverse
(因为它修改了列表) .
到目前为止,我在这里看到的最简洁的方法是实现我自己的 Spliterator
版本 ORDERED
并反向推进列表,或实现反向迭代的 Iterator
,并使用 Spliterators.spliteratorUnknownSize(iterator,ORDERED)
.
注意这个问题与Java 8 stream reverse order不同:其他问题询问如何反转流(这在一般情况下是不可能的),并且答案提供以某种方式反转源(我不想做),然后流逆源 . 逆转源的成本是O(N),如果可能的话我想完全避免它 .
4 回答
如果您的
List
是随机访问列表,您可以使用创建具有
ORDERED | SIZED | SUBSIZED
特征的Stream
并提供完全拆分支持 .对于像
LinkedList
这样的非随机访问列表,它会是一场性能灾难,但是,无论如何,谁使用LinkedList
?您也可以先通过
list instanceof
RandomAccess进行检查......NOTE: 如果您有
ArrayList
或其他允许按索引(get(i)
)进行随机访问检索的列表,则最好使用Holger's approach . 只有拥有允许反向遍历但不允许索引访问的数据结构时,才需要使用下面的方法 .不幸的是,似乎没有一种非常简单(即单行)的方式来做到这一点 . 但是使用
AbstractSpliterator
获得反向流并不太难,因为List
已经具有反向迭代的能力 . 这是一个实用方法:(我猜Spliterator可能是
SIZED
,但这大多没有意义,因为这是unsplittable spliterator . )就目前而言,这可以提供有限程度的并行性,因为
AbstractSpliterator
将多次调用tryAdvance
并批量处理以交付到fork-join任务 . 但它没有能够分裂的效率 .如果并行效率是一个很大的问题,那么可以编写一个可以实际拆分的分裂器,其中拆分以相反的顺序遍历 .
我倾向于喜欢@teppic 's answer of using a third-party library to do this. However, it'这是一个有趣的练习,试图仅使用Java 8 API来提出解决方案 . 委托
ListIterator
是我能想到的最干净的东西,但它并不比从头开始实现你自己的_707846更干净 .Google的Guava库提供了列表的反向视图(Lists#reverse(List)) . Apache Commons Collection库中也有ReverseListIterator .