我正在迁移一段代码以使用泛型。这样做的一个理由是,for循环比跟踪索引或使用显式迭代器干净得多。
在大约一半的情况下,列表(ArrayList)通过使用索引以相反的顺序迭代。
谁能建议一种更干净的方法来做到这一点(因为我不喜欢索引for循环时使用集合),尽管它确实有效?
for (int i = nodes.size() - 1; i >= 0; i--) {
final Node each = (Node) nodes.get(i);
...
}
注意:我不能在JDK之外添加任何新的依赖项。
下面是一个(未经测试的)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()));
}
}
选项1:你有没有想过用Collections#reverse()反转列表,然后使用foreach?
当然,您可能还想重构代码,使列表的顺序正确,这样就不必反转它,这会占用额外的空间/时间。
编辑:
选项2:或者,您可以使用Deque而不是数组列表吗?它将允许您向前和向后迭代
编辑:
选项3:正如其他人建议的那样,你可以编写一个Iterator,它将反向遍历列表,下面是一个例子:
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);
}