java.util.List 的降序迭代器 [英] descendingIterator for java.util.List

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

问题描述

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

LinkedListlist = new LinkedList();...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("反向:\n" + sJ2.toString());

<块引用>

厌恶:你好 2 巧克力 10逆转:10 巧克力 2 你好

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

问题类似于可以以相反的顺序对 java 中的每个循环执行一次?.但所有答案都推荐临时解决方案或第 3 方库.

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

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

  • 使用流只是一种选择,问题是关于java.util.Iteratorjava.util.List
  • 该问题的答案仅解决了部分情况,但显示没有方便的一般反向.如果我没有遗漏术语 List 是有序集合,可比较项的排序,以实现顺序减小范围.

解决方案

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

这里有一个小实用方法,它使 Iterable 适应以相反顺序迭代的 ListIterator:

static 可迭代的<T>降序Iterable(列表列表){返回 () ->{列表迭代器li = list.listIterator(list.size());返回新的迭代器(){public boolean hasNext() { return li.hasPrevious();}公共 T next() { return li.previous();}};};}

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

Listlist = Arrays.asList("你好", "2", "巧克力", "10");StringJoiner sj = new StringJoiner(" ");降序迭代器(列表).迭代器().forEachRemaining(sj::add);System.out.println(sj);10 巧克力 2 你好

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

for (String s :DescingIterable(list)) {System.out.println(s);}10巧克力2你好

我最初让它创建了一个 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 的降序迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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