一个人可以按照相反的顺序在java中执行每个循环吗?
我需要使用Java以相反的顺序遍历List。
那么它在哪里转发:
for(String string: stringList){ //...do something }
有没有一些方法来使用for each语法以相反的顺序迭代stringList?
为了清楚起见:我知道如何以相反的顺序迭代列表,但想知道(为了好奇)如何在每个样式中执行它。
不要使用Collections.reverse方法,它实际上会颠倒原始列表。 如果你使用它:
错误的方法!
Collections.reverse(new ArrayList(stringList))
为了避免修改原始文件,这将返回一个新列表,其中原始列表的元素以相反的顺序复制到列表中,并且对于原始列表的大小具有O(n)性能和空间要求。
作为一个更高效的解决scheme,你可以编写一个类来呈现一个List的反转视图作为一个Iterablegenerics。 您的类返回的迭代器将使用装饰列表的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); }
有关列表,您可以使用Google Guava Library :
for (String item : Lists.reverse(stringList)) { // ... }
请注意, Lists.reverse
不会颠倒整个集合,或者做任何类似的事情 – 它只是允许以相反的顺序进行迭代和随机访问。 这比首先倒转collections更有效率。
为了反转任意的迭代,你必须全部阅读,然后“回放”它。
(如果你还没有使用它,我build议你看一下番石榴 ,这是很棒的东西。)
List(与Set不同)是一个有序的集合,迭代它可以保持合同的顺序。 我会期望一个堆栈以相反的顺序迭代,但不幸的是它不。 所以我能想到的最简单的解决scheme是:
for (int i = stack.size() - 1; i >= 0; i--) { System.out.println(stack.get(i)); }
我意识到这不是一个“每个”循环解决scheme。 我宁愿使用for循环,而不是引入像Google Collections这样的新库。
Collections.reverse()也可以完成这个工作,但它会更新列表,而不是以相反的顺序返回一个副本。
这将与原始列表混淆,也需要在循环之外调用。 你也不想在每次循环时进行反向操作 – 如果应用了一个Iterables.reverse ideas
,那么这是否是真实的?
Collections.reverse(stringList); for(String string: stringList){ //...do something }
AFAIK在标准库中没有标准的“reverse_iterator”类的东西,它支持for-each语法,这个语法已经是一个语法上的迟到了。
你可以这样做(Item元素:myList.clone()。reverse())并支付相关的价格。
这看起来与表面上看起来相当一致,不会给你提供方便的昂贵的操作方式,因为根据定义,一个列表可能具有O(N)随机访问的复杂性(你可以用一个单一链接实现接口),反向迭代最终可能是O(N ^ 2)。 当然,如果你有一个ArrayList,你不支付这个价格。
不是没有写一些自定义的代码,它会给你一个枚举器,它将为你反转元素。
你应该可以通过创build一个自定义的Iterable实现来完成,它将以相反的顺序返回元素。
然后,你将实例化包装器(或者调用方法,what-have-you),这将返回Iterable实现,该实现反转每个循环中的元素。
如果您想要使用每种语法的语法并按相反的顺序进行操作,则需要将您的collections反转。
这可能是一个select。 希望有一个更好的方法,从最后一个元素开始,而不是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 Commons ReverseListIterator
Iterable<String> reverse = new IteratorIterable(new ReverseListIterator(stringList)); for(String string: reverse ){ //...do something }
正如@rogerdpack所说的 ,你需要将ReverseListIterator
作为Iterable
包装起来。
以上所有答案只能满足要求,可以通过包装另一种方法或者在外面调用一些外部代码;
这是从Thinking in Java第4版 ,第11.13.1章AdapterMethodIdiom复制的解决scheme;
这里是代码:
// 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 *///:~