java.util.List的descendingIterator

use*_*999 4 java linked-list arraylist 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());
Run Code Online (Sandbox Code Playgroud)
averse: 
Hello 2 Chocolate 10
reverse: 
10 Chocolate 2 Hello
Run Code Online (Sandbox Code Playgroud)

但是descendingIterator不适用于ListArrayList.有没有在列表说明任何解决办法,或者为什么的descendingIterator缺席的名单

问题类似于可以为java中的每个循环以相反的顺序执行吗?.但所有答案都建议使用临时解决方案或第三方库.

可能有使用溪流可能吗?(不幸的是,我的谷歌搜索只给出了流Java 8流逆序的缺失标准反转)

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

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

Stu*_*rks 6

没有一个很好的理由为什么List不能有一个降序迭代器.每个List都需要支持一个ListIterator可以使用hasPrevious()previous()方法以相反的顺序迭代.不过,这似乎是一个相当罕见的用例.

这是一个小实用程序方法,它IterableListIterator相反的顺序调整迭代:

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(); }
        };
    };
}
Run Code Online (Sandbox Code Playgroud)

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

    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
Run Code Online (Sandbox Code Playgroud)

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

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

    10
    Chocolate
    2
    Hello
Run Code Online (Sandbox Code Playgroud)

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

还要注意,这里有一个小皱纹,即如果List可以同时修改则存在竞争条件.这发生在这里的代码:

        list.listIterator(list.size())
Run Code Online (Sandbox Code Playgroud)

如果有可能,您必须在列表中使用外部同步,或者如果列表是a CopyOnWriteArrayList,则必须先克隆它.有关后者的更多信息,请参阅此答案.


Mag*_*nus 4

有没有关于为什么List 中没有DescendingIterator 的解释?

迭代列表的效率高度依赖于该列表的实现。
在设计接口时,您通常希望该接口适合其任何可能的实现。

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);
Run Code Online (Sandbox Code Playgroud)