在java中以相反顺序遍历列表[复制]

时间:2022-11-27 20:18:32

This question already has an answer here:

这个问题已经有了答案:

I'm migrating a piece of code to make use of generics. One argument for doing so is that the for loop is much cleaner than keeping track of indexes, or using an explicit iterator.

我正在迁移一段代码来使用泛型。这样做的一个理由是,for循环比跟踪索引或使用显式迭代器要干净得多。

In about half the cases, the list (an ArrayList) is being iterated in reverse order by using an index today.

在大约一半的情况下,列表(ArrayList)通过使用索引按逆向顺序进行迭代。

Can someone suggest a cleaner way of doing this (since I dislike the indexed for loop when working with collections), though it does work?

有人能提出一种更干净的方法来实现这一点吗(因为我不喜欢在处理集合时使用索引for循环),尽管它确实有效?

 for (int i = nodes.size() - 1; i >= 0; i--) {
    final Node each = (Node) nodes.get(i);
    ...
 }

Note: I can't add any new dependencies outside the JDK.

注意:我不能在JDK之外添加任何新的依赖项。

15 个解决方案

#1


386  

Try this:

试试这个:

// Substitute appropriate type.
ArrayList<...> a = new ArrayList<...>();

// Add elements to list.

// Generate an iterator. Start just after the last element.
ListIterator li = a.listIterator(a.size());

// Iterate in reverse.
while(li.hasPrevious()) {
  System.out.println(li.previous());
}

#2


26  

Guava offers Lists#reverse(List) and ImmutableList#reverse(). As in most cases for Guava, the former delegates to the latter if the argument is an ImmutableList, so you can use the former in all cases. These do not create new copies of the list but just "reversed views" of it.

Guava提供列表#reverse(List)和ImmutableList#reverse()。就像在大多数情况下的番石榴一样,如果争论是一个不可改变的列表,那么前代表就会代表后者,因此您可以在所有情况下都使用前者。它们不会创建列表的新副本,而只是对列表的“反向视图”。

Example

例子

List reversed = ImmutableList.copyOf(myList).reverse();

#3


20  

I don't think it's possible using the for loop syntax. The only thing I can suggest is to do something like:

我认为使用for循环语法是不可能的。我唯一能建议的就是做以下事情:

Collections.reverse(list);
for (Object o : list) {
  ...
}

... but I wouldn't say this is "cleaner" given that it's going to be less efficient.

…但我不会说这是“干净”的,因为它的效率会更低。

#4


12  

Option 1: Have you thought about reversing the List with Collections#reverse() and then using foreach?

选项1:您是否考虑过使用Collections#reverse()和foreach来反转列表?

Of course, you may also want to refactor your code such that the list is ordered correctly so you don't have to reverse it, which uses extra space/time.

当然,您可能还想重构代码,使列表被正确排序,这样您就不必逆转它,这将占用额外的空间/时间。


EDIT:

编辑:

Option 2: Alternatively, could you use a Deque instead of an ArrayList? It will allow you to iterate forwards and backwards

选项2:或者,你可以用Deque代替ArrayList吗?它将允许您向前和向后迭代


EDIT:

编辑:

Option 3: As others have suggested, you could write an Iterator that will go through the list in reverse, here is an example:

选项3:正如其他人所建议的,您可以编写一个迭代器,它将反向遍历列表,这里有一个示例:

import java.util.Iterator;
import java.util.List;

public class ReverseIterator<T> implements Iterator<T>, Iterable<T> {

    private final List<T> list;
    private int position;

    public ReverseIterator(List<T> list) {
        this.list = list;
        this.position = list.size() - 1;
    }

    @Override
    public Iterator<T> iterator() {
        return this;
    }

    @Override
    public boolean hasNext() {
        return position >= 0;
    }

    @Override
    public T next() {
        return list.get(position--);
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException();
    }

}


List<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add("E");

for (String s : new ReverseIterator<String>(list)) {
    System.out.println(s);
}

#5


8  

You could use the concrete class LinkedList instead of the general interface List. Then you have a descendingIterator for iterating with the reverse direction.

您可以使用具体的类LinkedList而不是通用接口列表。然后,您有一个后代迭代器,用于反向迭代。

LinkedList<String > linkedList;
for( Iterator<String > it = linkedList.descendingIterator(); it.hasNext(); ) {
    String text = it.next();
}

Don't know why there is no descendingIterator with ArrayList...

不知道为什么ArrayList没有后代迭代器……

#6


6  

Create a custom reverseIterable

创建一个自定义reverseIterable

#7


4  

Here is an (untested) implementation of a ReverseIterable. When iterator() is called it creates and returns a private ReverseIterator implementation, which simply maps calls to hasNext() to hasPrevious() and calls to next() are mapped to previous(). It means you could iterate over an ArrayList in reverse as follows:

这是一个(未经测试的)可反向迭代的实现。当迭代器()被调用时,它创建并返回一个私有的ReverseIterator实现,它简单地将调用hasNext()映射到hasPrevious()并调用next()映射到以前的()。这意味着你可以对ArrayList进行反向迭代,如下所示:

ArrayList<String> l = ...
for (String s : new ReverseIterable(l)) {
  System.err.println(s);
}

Class Definition

类定义

public class ReverseIterable<T> implements Iterable<T> {
  private static class ReverseIterator<T> implements Iterator {
    private final ListIterator<T> it;

    public boolean hasNext() {
      return it.hasPrevious();
    }

    public T next() {
      return it.previous();
    }

    public void remove() {
      it.remove();
    }
  }

  private final ArrayList<T> l;

  public ReverseIterable(ArrayList<T> l) {
    this.l = l;
  }

  public Iterator<T> iterator() {
    return new ReverseIterator(l.listIterator(l.size()));
  }
}

#8


4  

If the lists are fairly small so that performance is not a real issue, one can use the reverse-metod of the Lists-class in Google Guava. Yields pretty for-each-code, and the original list stays the same. Also, the reversed list is backed by the original list, so any change to the original list will be reflected in the reversed one.

如果列表相当小,因此性能不是一个真正的问题,那么可以使用谷歌Guava中的lists类的reverse-metod。生成非常适合每个代码的代码,并且原始列表保持不变。另外,反向列表是由原始列表支持的,所以对原始列表的任何更改都将反映在相反的列表中。

import com.google.common.collect.Lists;

[...]

final List<String> myList = Lists.newArrayList("one", "two", "three");
final List<String> myReverseList = Lists.reverse(myList);

System.out.println(myList);
System.out.println(myReverseList);

myList.add("four");

System.out.println(myList);
System.out.println(myReverseList);

Yields the following result:

会产生如下结果:

[one, two, three]
[three, two, one]
[one, two, three, four]
[four, three, two, one]

Which means that reverse iteration of myList can be written as:

这意味着myList的反向迭代可以写成:

for (final String someString : Lists.reverse(myList)) {
    //do something
}

#9


4  

This is an old question, but it's lacking a java8-friendly answer. Here are some ways of reverse-iterating the list, with the help of the Streaming API:

这是一个古老的问题,但它缺乏对java友好的答案。下面是在流API的帮助下反向迭代列表的一些方法:

List<Integer> list = new ArrayList<Integer>(Arrays.asList(1, 3, 3, 7, 5));
list.stream().forEach(System.out::println); // 1 3 3 7 5

ListIterator<Integer> it = list.listIterator(list.size());
Stream.generate(it::previous).limit(list.size())
    .forEach(System.out::println); // 5 7 3 3 1

ListIterator<Integer> it2 = list.listIterator(list.size());
Stream.iterate(it2.previous(), i -> it2.previous()).limit(list.size())
    .forEach(System.out::println); // 5 7 3 3 1

// If list is RandomAccess (i.e. an ArrayList)
IntStream.range(0, list.size()).map(i -> list.size() - i - 1).map(list::get)
    .forEach(System.out::println); // 5 7 3 3 1

// If list is RandomAccess (i.e. an ArrayList)
IntStream.range(0, list.size()).boxed().sorted(Comparator.reverseOrder())
    .map(list::get).forEach(System.out::println); // 5 7 3 3 1

#10


3  

Very simple Example:

很简单的例子:

List<String> list = new ArrayList<String>();

list.add("ravi");

list.add("kant");

list.add("soni");

// Iterate to disply : result will be as ---     ravi kant soni

for (String name : list) {
  ...
}

//Now call this method

Collections.reverse(list);

// iterate and print index wise : result will be as ---     soni kant ravi

for (String name : list) {
  ...
}

#11


2  

Also found google collections reverse method.

还找到了谷歌集合反向的方法。

#12


2  

You could use ReverseListIterator from Apache Commons-Collections:

您可以使用Apache common - collections的ReverseListIterator:

https://commons.apache.org/proper/commons-collections/javadocs/api-3.2.1/org/apache/commons/collections/iterators/ReverseListIterator.html

https://commons.apache.org/proper/commons-collections/javadocs/api-3.2.1/org/apache/commons/collections/iterators/ReverseListIterator.html

#13


2  

To have code which looks like this:

要有这样的代码:

List<Item> items;
...
for (Item item : In.reverse(items))
{
    ...
}

Put this code into a file called "In.java":

将此代码放入名为“In.java”的文件中:

import java.util.*;

public enum In {;
    public static final <T> Iterable<T> reverse(final List<T> list) {
        return new ListReverseIterable<T>(list);
    }

    class ListReverseIterable<T> implements Iterable<T> {
        private final List<T> mList;

        public ListReverseIterable(final List<T> list) {
            mList = list;
        }

        public Iterator<T> iterator() {
            return new Iterator<T>() {
                final ListIterator<T> it = mList.listIterator(mList.size());

                public boolean hasNext() {
                    return it.hasPrevious();
                }
                public T next() {
                    return it.previous();
                }
                public void remove() {
                    it.remove();
                }
            };
        }
    }
}

#14


0  

As has been suggested at least twice, you can use descendingIterator with a Deque, in particular with a LinkedList. If you want to use the for-each loop (i.e., have an Iterable), you can construct and use a wraper like this:

正如至少已经建议的那样,您可以使用带有Deque的后代迭代器,特别是使用LinkedList。如果您想使用for-each循环(例如。),你可以构造并使用如下的包装:

import java.util.*;

public class Main {

    public static class ReverseIterating<T> implements Iterable<T> {
        private final LinkedList<T> list;

        public ReverseIterating(LinkedList<T> list) {
            this.list = list;
        }

        @Override
        public Iterator<T> iterator() {
            return list.descendingIterator();
        }
    }

    public static void main(String... args) {
        LinkedList<String> list = new LinkedList<String>();
        list.add("A");
        list.add("B");
        list.add("C");
        list.add("D");
        list.add("E");

        for (String s : new ReverseIterating<String>(list)) {
            System.out.println(s);
        }
    }
}

#15


-9  

Reason : "Don't know why there is no descendingIterator with ArrayList..."

理由:“不知道为什么没有带有ArrayList的后代迭代器……”

Since array list doesnot keep the list in the same order as data has been added to list. So, never use Arraylist .

由于数组列表没有按照添加到列表中的数据保存列表。所以,永远不要使用Arraylist。

Linked list will keep the data in same order of ADD to list.

链表将使数据按照ADD to list的顺序保持一致。

So , above in my example, i used ArrayList() in order to make user to twist their mind and make them to workout something from their side.

因此,在上面的示例中,我使用了ArrayList(),目的是让用户扭曲他们的想法,并让他们从他们的一边锻炼一些东西。

Instead of this

而不是这个

List<String> list = new ArrayList<String>();

USE:

使用:

List<String> list = new LinkedList<String>();

list.add("ravi");

list.add("kant");

list.add("soni");

// Iterate to disply : result will be as ---     ravi kant soni

for (String name : list) {
  ...
}

//Now call this method

Collections.reverse(list);

// iterate and print index wise : result will be as ---     soni kant ravi

for (String name : list) {
  ...
}

#1


386  

Try this:

试试这个:

// Substitute appropriate type.
ArrayList<...> a = new ArrayList<...>();

// Add elements to list.

// Generate an iterator. Start just after the last element.
ListIterator li = a.listIterator(a.size());

// Iterate in reverse.
while(li.hasPrevious()) {
  System.out.println(li.previous());
}

#2


26  

Guava offers Lists#reverse(List) and ImmutableList#reverse(). As in most cases for Guava, the former delegates to the latter if the argument is an ImmutableList, so you can use the former in all cases. These do not create new copies of the list but just "reversed views" of it.

Guava提供列表#reverse(List)和ImmutableList#reverse()。就像在大多数情况下的番石榴一样,如果争论是一个不可改变的列表,那么前代表就会代表后者,因此您可以在所有情况下都使用前者。它们不会创建列表的新副本,而只是对列表的“反向视图”。

Example

例子

List reversed = ImmutableList.copyOf(myList).reverse();

#3


20  

I don't think it's possible using the for loop syntax. The only thing I can suggest is to do something like:

我认为使用for循环语法是不可能的。我唯一能建议的就是做以下事情:

Collections.reverse(list);
for (Object o : list) {
  ...
}

... but I wouldn't say this is "cleaner" given that it's going to be less efficient.

…但我不会说这是“干净”的,因为它的效率会更低。

#4


12  

Option 1: Have you thought about reversing the List with Collections#reverse() and then using foreach?

选项1:您是否考虑过使用Collections#reverse()和foreach来反转列表?

Of course, you may also want to refactor your code such that the list is ordered correctly so you don't have to reverse it, which uses extra space/time.

当然,您可能还想重构代码,使列表被正确排序,这样您就不必逆转它,这将占用额外的空间/时间。


EDIT:

编辑:

Option 2: Alternatively, could you use a Deque instead of an ArrayList? It will allow you to iterate forwards and backwards

选项2:或者,你可以用Deque代替ArrayList吗?它将允许您向前和向后迭代


EDIT:

编辑:

Option 3: As others have suggested, you could write an Iterator that will go through the list in reverse, here is an example:

选项3:正如其他人所建议的,您可以编写一个迭代器,它将反向遍历列表,这里有一个示例:

import java.util.Iterator;
import java.util.List;

public class ReverseIterator<T> implements Iterator<T>, Iterable<T> {

    private final List<T> list;
    private int position;

    public ReverseIterator(List<T> list) {
        this.list = list;
        this.position = list.size() - 1;
    }

    @Override
    public Iterator<T> iterator() {
        return this;
    }

    @Override
    public boolean hasNext() {
        return position >= 0;
    }

    @Override
    public T next() {
        return list.get(position--);
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException();
    }

}


List<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add("E");

for (String s : new ReverseIterator<String>(list)) {
    System.out.println(s);
}

#5


8  

You could use the concrete class LinkedList instead of the general interface List. Then you have a descendingIterator for iterating with the reverse direction.

您可以使用具体的类LinkedList而不是通用接口列表。然后,您有一个后代迭代器,用于反向迭代。

LinkedList<String > linkedList;
for( Iterator<String > it = linkedList.descendingIterator(); it.hasNext(); ) {
    String text = it.next();
}

Don't know why there is no descendingIterator with ArrayList...

不知道为什么ArrayList没有后代迭代器……

#6


6  

Create a custom reverseIterable

创建一个自定义reverseIterable

#7


4  

Here is an (untested) implementation of a ReverseIterable. When iterator() is called it creates and returns a private ReverseIterator implementation, which simply maps calls to hasNext() to hasPrevious() and calls to next() are mapped to previous(). It means you could iterate over an ArrayList in reverse as follows:

这是一个(未经测试的)可反向迭代的实现。当迭代器()被调用时,它创建并返回一个私有的ReverseIterator实现,它简单地将调用hasNext()映射到hasPrevious()并调用next()映射到以前的()。这意味着你可以对ArrayList进行反向迭代,如下所示:

ArrayList<String> l = ...
for (String s : new ReverseIterable(l)) {
  System.err.println(s);
}

Class Definition

类定义

public class ReverseIterable<T> implements Iterable<T> {
  private static class ReverseIterator<T> implements Iterator {
    private final ListIterator<T> it;

    public boolean hasNext() {
      return it.hasPrevious();
    }

    public T next() {
      return it.previous();
    }

    public void remove() {
      it.remove();
    }
  }

  private final ArrayList<T> l;

  public ReverseIterable(ArrayList<T> l) {
    this.l = l;
  }

  public Iterator<T> iterator() {
    return new ReverseIterator(l.listIterator(l.size()));
  }
}

#8


4  

If the lists are fairly small so that performance is not a real issue, one can use the reverse-metod of the Lists-class in Google Guava. Yields pretty for-each-code, and the original list stays the same. Also, the reversed list is backed by the original list, so any change to the original list will be reflected in the reversed one.

如果列表相当小,因此性能不是一个真正的问题,那么可以使用谷歌Guava中的lists类的reverse-metod。生成非常适合每个代码的代码,并且原始列表保持不变。另外,反向列表是由原始列表支持的,所以对原始列表的任何更改都将反映在相反的列表中。

import com.google.common.collect.Lists;

[...]

final List<String> myList = Lists.newArrayList("one", "two", "three");
final List<String> myReverseList = Lists.reverse(myList);

System.out.println(myList);
System.out.println(myReverseList);

myList.add("four");

System.out.println(myList);
System.out.println(myReverseList);

Yields the following result:

会产生如下结果:

[one, two, three]
[three, two, one]
[one, two, three, four]
[four, three, two, one]

Which means that reverse iteration of myList can be written as:

这意味着myList的反向迭代可以写成:

for (final String someString : Lists.reverse(myList)) {
    //do something
}

#9


4  

This is an old question, but it's lacking a java8-friendly answer. Here are some ways of reverse-iterating the list, with the help of the Streaming API:

这是一个古老的问题,但它缺乏对java友好的答案。下面是在流API的帮助下反向迭代列表的一些方法:

List<Integer> list = new ArrayList<Integer>(Arrays.asList(1, 3, 3, 7, 5));
list.stream().forEach(System.out::println); // 1 3 3 7 5

ListIterator<Integer> it = list.listIterator(list.size());
Stream.generate(it::previous).limit(list.size())
    .forEach(System.out::println); // 5 7 3 3 1

ListIterator<Integer> it2 = list.listIterator(list.size());
Stream.iterate(it2.previous(), i -> it2.previous()).limit(list.size())
    .forEach(System.out::println); // 5 7 3 3 1

// If list is RandomAccess (i.e. an ArrayList)
IntStream.range(0, list.size()).map(i -> list.size() - i - 1).map(list::get)
    .forEach(System.out::println); // 5 7 3 3 1

// If list is RandomAccess (i.e. an ArrayList)
IntStream.range(0, list.size()).boxed().sorted(Comparator.reverseOrder())
    .map(list::get).forEach(System.out::println); // 5 7 3 3 1

#10


3  

Very simple Example:

很简单的例子:

List<String> list = new ArrayList<String>();

list.add("ravi");

list.add("kant");

list.add("soni");

// Iterate to disply : result will be as ---     ravi kant soni

for (String name : list) {
  ...
}

//Now call this method

Collections.reverse(list);

// iterate and print index wise : result will be as ---     soni kant ravi

for (String name : list) {
  ...
}

#11


2  

Also found google collections reverse method.

还找到了谷歌集合反向的方法。

#12


2  

You could use ReverseListIterator from Apache Commons-Collections:

您可以使用Apache common - collections的ReverseListIterator:

https://commons.apache.org/proper/commons-collections/javadocs/api-3.2.1/org/apache/commons/collections/iterators/ReverseListIterator.html

https://commons.apache.org/proper/commons-collections/javadocs/api-3.2.1/org/apache/commons/collections/iterators/ReverseListIterator.html

#13


2  

To have code which looks like this:

要有这样的代码:

List<Item> items;
...
for (Item item : In.reverse(items))
{
    ...
}

Put this code into a file called "In.java":

将此代码放入名为“In.java”的文件中:

import java.util.*;

public enum In {;
    public static final <T> Iterable<T> reverse(final List<T> list) {
        return new ListReverseIterable<T>(list);
    }

    class ListReverseIterable<T> implements Iterable<T> {
        private final List<T> mList;

        public ListReverseIterable(final List<T> list) {
            mList = list;
        }

        public Iterator<T> iterator() {
            return new Iterator<T>() {
                final ListIterator<T> it = mList.listIterator(mList.size());

                public boolean hasNext() {
                    return it.hasPrevious();
                }
                public T next() {
                    return it.previous();
                }
                public void remove() {
                    it.remove();
                }
            };
        }
    }
}

#14


0  

As has been suggested at least twice, you can use descendingIterator with a Deque, in particular with a LinkedList. If you want to use the for-each loop (i.e., have an Iterable), you can construct and use a wraper like this:

正如至少已经建议的那样,您可以使用带有Deque的后代迭代器,特别是使用LinkedList。如果您想使用for-each循环(例如。),你可以构造并使用如下的包装:

import java.util.*;

public class Main {

    public static class ReverseIterating<T> implements Iterable<T> {
        private final LinkedList<T> list;

        public ReverseIterating(LinkedList<T> list) {
            this.list = list;
        }

        @Override
        public Iterator<T> iterator() {
            return list.descendingIterator();
        }
    }

    public static void main(String... args) {
        LinkedList<String> list = new LinkedList<String>();
        list.add("A");
        list.add("B");
        list.add("C");
        list.add("D");
        list.add("E");

        for (String s : new ReverseIterating<String>(list)) {
            System.out.println(s);
        }
    }
}

#15


-9  

Reason : "Don't know why there is no descendingIterator with ArrayList..."

理由:“不知道为什么没有带有ArrayList的后代迭代器……”

Since array list doesnot keep the list in the same order as data has been added to list. So, never use Arraylist .

由于数组列表没有按照添加到列表中的数据保存列表。所以,永远不要使用Arraylist。

Linked list will keep the data in same order of ADD to list.

链表将使数据按照ADD to list的顺序保持一致。

So , above in my example, i used ArrayList() in order to make user to twist their mind and make them to workout something from their side.

因此,在上面的示例中,我使用了ArrayList(),目的是让用户扭曲他们的想法,并让他们从他们的一边锻炼一些东西。

Instead of this

而不是这个

List<String> list = new ArrayList<String>();

USE:

使用:

List<String> list = new LinkedList<String>();

list.add("ravi");

list.add("kant");

list.add("soni");

// Iterate to disply : result will be as ---     ravi kant soni

for (String name : list) {
  ...
}

//Now call this method

Collections.reverse(list);

// iterate and print index wise : result will be as ---     soni kant ravi

for (String name : list) {
  ...
}