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

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

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

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

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


当前回答

原因:“不知道为什么没有ArrayList的descent iterator…”

因为数组列表不保持列表在相同的顺序,因为数据已添加到列表。所以,千万不要用数组列表。

链表将保持数据与ADD到list的顺序相同。

所以,在上面的例子中,我使用了ArrayList()来让用户扭曲他们的思想,让他们从他们的角度去锻炼一些东西。

而不是这个

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) {
  ...
}

其他回答

这是一个老问题,但它缺乏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

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

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

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

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

原因:“不知道为什么没有ArrayList的descent iterator…”

因为数组列表不保持列表在相同的顺序,因为数据已添加到列表。所以,千万不要用数组列表。

链表将保持数据与ADD到list的顺序相同。

所以,在上面的例子中,我使用了ArrayList()来让用户扭曲他们的思想,让他们从他们的角度去锻炼一些东西。

而不是这个

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) {
  ...
}

如果列表相当小,因此性能不是真正的问题,则可以使用谷歌Guava中的lists类的反向方法。每个代码都产生相当的结果,并且原始列表保持不变。另外,反向列表是由原始列表支持的,因此对原始列表的任何更改都将反映在反向列表中。

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

产生如下结果:

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

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

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