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

在大约一半的情况下,列表(ArrayList)通过使用索引以相反的顺序迭代。

谁能建议一种更干净的方法来做到这一点(因为我不喜欢索引for循环时使用集合),尽管它确实有效?

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

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


当前回答

试试这个:

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

其他回答

如何使用DeQue:

  var queue = new ArrayDeque<>(list);
  while (!queue.isEmpty()) {
    var first = reversed ? queue.removeLast() : queue.removeFirst();
    var second = reversed ? queue.peekLast() : queue.peekFirst();
    if (second != null) {
      //your code goes here
    }
  }

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

代码如下所示:

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

把这段代码放到一个名为“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();
                }
            };
        }
    }
}

Guava提供Lists#reverse(List)和ImmutableList#reverse()。在Guava的大多数情况下,如果参数是ImmutableList,则前者将委托给后者,因此可以在所有情况下使用前者。它们不会创建列表的新副本,而只是列表的“反向视图”。

例子

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

下面是一个(未经测试的)ReverseIterable的实现。当iterator()被调用时,它创建并返回一个私有的ReverseIterator实现,它简单地将对hasNext()的调用映射到hasPrevious(),并将对next()的调用映射到previous()。这意味着你可以逆向遍历一个数组列表,如下所示:

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

类定义

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