java.util.List的descendingIterator

时间:2017-02-14 21:33:48

标签: java arraylist linked-list java-8

LinkedList 可以使用升序或降序迭代器进行迭代:

       LinkedList<Object> list = new LinkedList<Object>();
       ...
   StringJoiner sJ1 = new StringJoiner(" ");
   list.iterator().forEachRemaining(a -> sJ1.add(a.toString()));
   System.out.println("averse: \n" + sJ1.toString());

   StringJoiner sJ2 = new StringJoiner(" ");
   list.descendingIterator().forEachRemaining(a -> sJ2.add(a.toString()));
   System.out.println("reverse: \n" + sJ2.toString());
averse: 
Hello 2 Chocolate 10
reverse: 
10 Chocolate 2 Hello

listndingIterator 不适用于 List ArrayList 。  是否有任何变通方法或列表说明,为什么 list descendingIterator 不存在?

问题类似于Can one do a for each loop in java in reverse order?。但所有答案都建议使用临时解决方案或第三方库。

可能有可能使用流媒体流吗? (不幸的是,我的Google搜索仅为流Java 8 stream reverse order提供了标准反转)

正如我所提到的,我的问题与流有关,但是:

  • 使用流只是一种选择,问题是关于java.util.Iteratorjava.util.List
  • 该问题的答案仅解决了部分案例,但显示缺乏方便的一般反向。如果我没有错过术语列表是有序集合,对可比项目进行排序,实现订单会缩小范围。

3 个答案:

答案 0 :(得分:5)

没有一个很好的理由说明List无法使用降序迭代器。每个List都需要支持ListIteratorhasPrevious()可以使用previous()Iterable方法以相反的顺序进行迭代。不过,这似乎是一个相当罕见的用例。

这是一个小实用程序方法,它以相反的顺序将ListIterator调整为static <T> Iterable<T> descendingIterable(List<? extends T> list) { return () -> { ListIterator<? extends T> li = list.listIterator(list.size()); return new Iterator<T>() { public boolean hasNext() { return li.hasPrevious(); } public T next() { return li.previous(); } }; }; } 迭代:

    List<String> list = Arrays.asList("Hello", "2", "Chocolate", "10");
    StringJoiner sj = new StringJoiner(" ");
    descendingIterable(list).iterator().forEachRemaining(sj::add);
    System.out.println(sj);

    10 Chocolate 2 Hello

您可以使用它来实现您的示例:

    for (String s : descendingIterable(list)) {
        System.out.println(s);
    }

    10
    Chocolate
    2
    Hello

或者您可以在增强型for循环中使用它:

Iterator

我最初创建了一个Iterable而不是List,但后者更有用,因为它可以在增强型for循环中使用。

另请注意,如果可以同时修改 list.listIterator(list.size()) ,则会出现一个小的皱纹。这发生在这里的代码:

CopyOnWriteArrayList

如果有可能,您必须在列表中使用外部同步,或者如果列表是complex_stuff = None def load_complex_stuff(): global complex_stuff if complex_stuff is None: import complex_stuff def func_using_it(): load_complex_stuff() ... more ... def func_using_it_2(): load_complex_stuff() ... more ... ,则必须先克隆它。有关后者的更多信息,请参阅this answer

答案 1 :(得分:4)

  

是否解释为什么列表中没有 descendingIterator

迭代List的效率在很大程度上取决于该列表的实现 在设计界面时,您通常希望界面适合于任何可能的实现。

Java链接列表是双重链接列表,这意味着每个元素都链接到它之前和之后的元素,因此可以编写有效的升序和降序迭代器。

如果您使用单个链接列表,那么迭代迭代它会非常低效,您需要遍历整个列表,直到每次迭代的当前索引。

我怀疑是出于这个原因,语言设计者决定从List接口中省略一个降序迭代器。

使用基于索引的方法可以相当容易地实现高效的ArrayList降序迭代器,在LinkedList上使用索引方法将比其首选实现慢得多。

下行迭代方法的一些示例:

for(int i=list.size() -1; i >= 0; i--){
    System.out.println(list.get(i));
}

IntStream.range(0, list.size())
        .map(i-> list.size() - 1 - i)
        .mapToObj(list::get)
        .forEach(System.out::println);

答案 2 :(得分:1)

我在这里看到两种可能的解决方案:

使用Intstream创建以相反顺序遍历列表的流:

IntStream.range(0, list.length())
    .mapToObj(i -> list.get(list.length() - i - 1)
    .forEach(...);

反转列表本身(如果您无法修改原始列表,则创建副本)

List<String> reversed = new ArrayList(list);
Collections.reverse(reversed);
reversed.stream()
    .forEach(...)