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

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

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

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

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


当前回答

如何使用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
    }
  }

其他回答

这是一个老问题,但它缺乏java8友好的答案。下面是在Streaming 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

int size = list.size();

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

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

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

// If list is RandomAccess (i.e. an ArrayList), less efficient due to sorting
IntStream.range(0, size).boxed().sorted(Comparator.reverseOrder())
    .map(list::get).forEach(System.out::println); // 5 7 3 3 1
Valid for Java 9+

List<String> strList = List.of("a", "b", "c", "d", "e");

IntStream.iterate(strList.size() - 1, i -> i >= 0, i -> --i)
         .mapToObj(strList::get)
         .forEach(System.out::println);

你可以使用Apache Commons-Collections中的ReverseListIterator:

https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/iterators/ReverseListIterator.html

如何使用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
    }
  }

试试这个:

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