java.util.List的DescendingIterator [英] descendingIterator for java.util.List

查看:186
本文介绍了java.util.List的DescendingIterator的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

但是 descendingIterator 不适用于 List ArrayList . 是否有任何解决方法或在列表说明中,为什么 List 中没有 descendingIterator ?

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

使用流流可能存在这种可能性吗? (不幸的是,我的谷歌搜索只针对流 Java 8流反向顺序)提供了标准的反向服务./p>

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

  • 仅使用流,一个问题是关于 java.util.List
  • 该问题的答案仅解决了部分情况,但显示出不方便进行一般性逆转.如果我不遗漏列表是有序集合"一词,则对可比较项进行排序,以实现排序会减小范围.

解决方案

List没有降序的迭代器没有充分的理由.每个List都需要支持一个ListIterator,可以使用hasPrevious()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循环中使用它:

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

10
Chocolate
2
Hello

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

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

list.listIterator(list.size())

如果可能的话,您必须在列表上使用外部同步,或者如果列表是CopyOnWriteArrayList,则必须先对其进行克隆.请参阅此答案以获取有关后者的更多信息.

LinkedList can be iterated using ascending or descending iterator like this:

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

But descendingIterator isn't available for List and ArrayList. Are there any workaround or at list explanation, why descendingIterator is absent in List?

Question is similar to Can one do a for each loop in java in reverse order?. But all the answers recommend ad hoc solutions or 3rd party libraries.

May be there is this is possible using streams streams? (Unfortunately my googling gives only absence standard reverse for stream Java 8 stream reverse order)

As I've mentioned my questions is related to that about streams, but:

  • Using of stream is only an option, question is about java.util.Iterator and java.util.List
  • Answers to that question solved only partial case, but showed absence of convenient general reverse. If I'm not missing the term List is ordered collection, sorting of Comparable items, to achieve order decreases the scope.

解决方案

There's no really good reason why List couldn't have a descending iterator. Every List is required to support a ListIterator which can be iterated in reverse order using the hasPrevious() and previous() methods. This seems to be a fairly uncommon use case, though.

Here's a little utility method that adapts an Iterable to a ListIterator iterating in reverse order:

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(); }
        };
    };
}

You could use it to implement your example:

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

Or you could use it in an enhanced-for loop:

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

10
Chocolate
2
Hello

I initially had this create an Iterator instead of an Iterable, but the latter is more useful since it can be used in an enhanced-for loop.

Note also there is a small wrinkle here which is that there is a race condition if the List can be concurrently modified. This occurs at the code here:

list.listIterator(list.size())

If this is a possibility, you either have to use external synchronization on the list, or if the list is a CopyOnWriteArrayList, you have to clone it first. See this answer for further information on the latter.

这篇关于java.util.List的DescendingIterator的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆