java中的foreach循环可以逆序执行吗?
题
我需要使用 Java 以相反的顺序运行列表。
那么它转发到哪里:
for(String string: stringList){
//...do something
}
有没有什么方法可以使用相反的顺序迭代 stringList 对于每个 句法?
为了清楚起见:我知道如何以相反的顺序迭代列表,但想知道(出于好奇)如何在 对于每个 风格。
解决方案
在Collections.reverse方法实际上返回与复制到它以相反的顺序原始列表的元素的新列表,因此这与关于原始列表的大小为O(n)的性能。
作为一个更有效的解决方案,可以编写呈现一个列表以Iterable的反转视图一个装饰。通过你的装饰返回的迭代器将使用装饰列表的ListIterator走过去以相反的顺序的元素。
例如:
public class Reversed<T> implements Iterable<T> {
private final List<T> original;
public Reversed(List<T> original) {
this.original = original;
}
public Iterator<T> iterator() {
final ListIterator<T> i = original.listIterator(original.size());
return new Iterator<T>() {
public boolean hasNext() { return i.hasPrevious(); }
public T next() { return i.previous(); }
public void remove() { i.remove(); }
};
}
public static <T> Reversed<T> reversed(List<T> original) {
return new Reversed<T>(original);
}
}
和你会使用它,如:
import static Reversed.reversed;
...
List<String> someStrings = getSomeStrings();
for (String s : reversed(someStrings)) {
doSomethingWith(s);
}
其他提示
对于列表,您可以使用 谷歌番石榴库:
for (String item : Lists.reverse(stringList))
{
// ...
}
注意 Lists.reverse
不 反转整个集合,或者做类似的事情 - 它只允许以相反的顺序进行迭代和随机访问。这比先逆向收集效率更高。
要反转任意可迭代对象,您必须读取全部内容,然后向后“重播”它。
(如果你还没有使用它,我会 彻底地 推荐你看看 番石榴. 。这是很棒的东西。)
在列表(不像集)是有序集合,并遍历它确实保留通过合同的顺序。我本来期望一个堆栈以相反的顺序来遍历但遗憾的是它没有。所以,我能想到的最简单的办法是这样的:
for (int i = stack.size() - 1; i >= 0; i--) {
System.out.println(stack.get(i));
}
我认识到,这不是一个“对每个”环溶液。我宁愿使用for循环比引进像谷歌集合了新库。
Collections.reverse()也做的工作,但它更新,而不是在相反的顺序返回副本列表。
这会搞乱与原来的列表,并且还需要在循环外部被调用。
你也不想进行反向每次循环的时间 - 如果应用该Iterables.reverse ideas
的人会认为是真实的。
Collections.reverse(stringList);
for(String string: stringList){
//...do something
}
据我所知还没有在标准库标准“reverse_iterator的”之类的事情,支持的for-each这已经是他们带来了晚成语言语法糖语法。
您可以做类似的(项目元素:myList.clone()反()),并支付相应的代价。
这似乎也有不给你方便的方式做昂贵的操作明显的现象相当一致的 - 因为一个列表,顾名思义,可以有O(N)的随机访问的复杂性(你可以实现与单链路的接口),反向迭代可能最终是O(N ^ 2)。当然,如果你有一个ArrayList,你不付出这样的代价。
这可能是一种选择。希望有一种更好的方式来从最后一个元素开始,而不是while循环的结束。
public static void main(String[] args) {
List<String> a = new ArrayList<String>();
a.add("1");a.add("2");a.add("3");a.add("4");a.add("5");
ListIterator<String> aIter=a.listIterator();
while(aIter.hasNext()) aIter.next();
for (;aIter.hasPrevious();)
{
String aVal = aIter.previous();
System.out.println(aVal);
}
}
作为的评论:你应该能够使用Apache下议院的 ReverseListIterator
Iterable<String> reverse
= new IteratorIterable(new ReverseListIterator(stringList));
for(String string: reverse ){
//...do something
}
如 @rogerdpack说,你需要用的ReverseListIterator
作为Iterable
。
不写入一些自定义代码,这将给你的枚举这将扭转元件为您服务。
您应该能够做到这一点在Java中通过创建可迭代的自定义实现,这将在相反的顺序返回元素。
然后,将实例化包装物(或调用该方法,什么具备的,你),其将返回可迭代执行该反转元件在每个循环。
可以使用类别类 HTTP ://java.sun.com/j2se/1.4.2/docs/api/java/util/Collections.html 的扭转列表然后循环
。您就需要扭转你的收藏,如果你想使用的每个语法开箱走在相反的顺序。
只有上述所有答案,或者通过包装另外方法或外部调用一些外来代码满足要求;
下面是从复制的溶液中的Java第四版思考,章11.13.1 AdapterMethodIdiom ;
下面是代码:
// The "Adapter Method" idiom allows you to use foreach
// with additional kinds of Iterables.
package holding;
import java.util.*;
@SuppressWarnings("serial")
class ReversibleArrayList<T> extends ArrayList<T> {
public ReversibleArrayList(Collection<T> c) { super(c); }
public Iterable<T> reversed() {
return new Iterable<T>() {
public Iterator<T> iterator() {
return new Iterator<T>() {
int current = size() - 1; //why this.size() or super.size() wrong?
public boolean hasNext() { return current > -1; }
public T next() { return get(current--); }
public void remove() { // Not implemented
throw new UnsupportedOperationException();
}
};
}
};
}
}
public class AdapterMethodIdiom {
public static void main(String[] args) {
ReversibleArrayList<String> ral =
new ReversibleArrayList<String>(
Arrays.asList("To be or not to be".split(" ")));
// Grabs the ordinary iterator via iterator():
for(String s : ral)
System.out.print(s + " ");
System.out.println();
// Hand it the Iterable of your choice
for(String s : ral.reversed())
System.out.print(s + " ");
}
} /* Output:
To be or not to be
be to not or be To
*///:~
绝对是这个问题的迟到答案。一种可能性是在 for 循环中使用 ListIterator。它不像冒号语法那么干净,但它确实有效。
List<String> exampleList = new ArrayList<>();
exampleList.add("One");
exampleList.add("Two");
exampleList.add("Three");
//Forward iteration
for (String currentString : exampleList) {
System.out.println(currentString);
}
//Reverse iteration
for (ListIterator<String> itr = exampleList.listIterator(exampleList.size()); itr.hasPrevious(); /*no-op*/ ) {
String currentString = itr.previous();
System.out.println(currentString);
}
ListIterator 语法的功劳在于 “在 Java 中迭代列表的方法”