我需要使用Java以相反顺序遍历List。可以按照相反的顺序对java中的每个循环执行一次吗?
那么,这确实是前锋:
for(String string: stringList){
//...do something
}
有没有一些方法来遍历的StringList以相反的顺序使用每个语法?
为清楚:我知道如何遍历以相反的顺序列表,但想知道(出于好奇的缘故)如何做到这一点的每个风格。
我需要使用Java以相反顺序遍历List。可以按照相反的顺序对java中的每个循环执行一次吗?
那么,这确实是前锋:
for(String string: stringList){
//...do something
}
有没有一些方法来遍历的StringList以相反的顺序使用每个语法?
为清楚:我知道如何遍历以相反的顺序列表,但想知道(出于好奇的缘故)如何做到这一点的每个风格。
不要使用Collections.reverse方法实际上颠倒了原始列表已到位。如果使用它:
错误的方式!
Collections.reverse(new ArrayList(stringList))
以避免修改原来,这返回与复制到它以相反的顺序原始列表的元素的新的列表,并且这样的为O与问候的大小(n)的性能和空间要求的原始列表。
作为一个更有效的解决方案,您可以编写一个类来呈现List作为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);
}
AFAIK在标准库中没有标准的“reverse_iterator”类标准库,它支持for-each语法,它已经是一种语法延迟的语法糖。
你可以做类似于(Item元素:myList.clone()。reverse())并支付相关的价格。
这似乎与不给你方便的昂贵操作方式的表面现象相当一致 - 因为根据定义,列表可能具有O(N)随机访问的复杂性(您可以使用单向函数实现接口)链接),反向迭代最终可能是O(N^2)。当然,如果你有一个ArrayList,你不会支付这个价格。
您可以向后运行一个ListIterator,它可以在Iterator中包装。 – 2009-07-08 13:52:18
@Tom:好点。但是,使用迭代器,您仍然在做烦人的旧式for循环,并且您仍然可能需要花费才能开始使用最后一个元素......不过,我在回答中添加了限定符,谢谢。 – Uri 2009-07-08 14:01:33
不是没有编写一些自定义代码,它会给你一个枚举器,它将为你反转元素。
您应该可以通过创建Iterable的自定义实现来完成它,它将以相反的顺序返回元素。然后,你将实例化包装器(或者调用方法,what-have-you),它将返回Iterable实现,该实现会颠倒每个循环中的元素。
您可以使用Collections类http://java.sun.com/j2se/1.4.2/docs/api/java/util/Collections.html来反转列表然后循环。
如果您想要使用每种语法的开箱即用方式,您需要将您的收藏反转。
有关列表,你可以使用Google Guava Library:
for (String item : Lists.reverse(stringList))
{
// ...
}
注意Lists.reverse
不扭转整个集合,或做那样的事情 - 它只是允许重复和随机存取,在相反的顺序。这比先倒收集效率更高。
要反转一个任意的迭代,你必须全部读完,然后“重放”它。
(如果你还没有使用它,我彻底建议你看看Guava。这是伟大的东西。)
这会搞乱与原来的列表,还需要在循环外部调用。 你也不想在每次循环时执行反向操作 - 如果应用了Iterables.reverse ideas
之一,那么这是真的吗?
Collections.reverse(stringList);
for(String string: stringList){
//...do something
}
这可能是一个选项。希望有一个更好的方法可以从最后一个元素开始,而不是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);
}
}
列表(与集合不同)是一个有序集合,迭代它可以保持订单的合同。我会希望堆栈以相反的顺序迭代,但不幸的是它没有。所以我能想到的最简单的解决方案是:
for (int i = stack.size() - 1; i >= 0; i--) {
System.out.println(stack.get(i));
}
我意识到这不是一个“for each”循环解决方案。我宁愿使用for循环,而不是引入像Google Collections这样的新库。
Collections.reverse()也可以完成这项工作,但它会更新列表,而不是以相反顺序返回副本。
由于the comment:你应该能够使用Apache下议院ReverseListIterator
Iterable<String> reverse
= new IteratorIterable(new ReverseListIterator(stringList));
for(String string: reverse){
//...do something
}
由于@rogerdpack said,你需要用的ReverseListIterator
为Iterable
。
以上所有答案只能满足要求,可以通过包装另一种方法或在外面调用某些外部代码;
下面是用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
*///:~
有趣的是,我中途读斯卡拉书与不可变列表操作交易...在缺乏表现力的一个很好的示范部分读出这个问题java的。 – skaffman 2009-07-08 13:37:49
“for-each”循环的要点是您只需要对每个元素执行操作,而顺序并不重要。因为每个人都可以按照完全随机的顺序处理元素,而且它仍然会按照设计的目的进行。如果您需要以特定方式处理元素,我会建议您手动进行。 – muusbolla 2009-07-08 13:46:19
Java集合库。与语言无关。怪乔希布洛赫。 – 2009-07-08 13:50:59