可以为java中的每个循环以相反的顺序执行a操作吗?

Ron*_*fin 143 java foreach reverse

我需要使用Java以相反的顺序运行List.

所以这是前进的地方:

for(String string: stringList){
//...do something
}
Run Code Online (Sandbox Code Playgroud)

有没有办法使用for each语法以相反的顺序迭代stringList ?

为了清楚起见:我知道如何以相反的顺序迭代列表但是想知道(出于好奇心)如何在每个样式中执行它.

Nat*_*Nat 149

不要使用Collections.reverse方法,它实际上反转原始列表.如果你使用它:

错误的方法!

__CODE__

为了避免修改原始文件,这将返回一个新列表,其中原始列表的元素以相反的顺序复制到其中,并且对于原始列表的大小具有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);
    }
}
Run Code Online (Sandbox Code Playgroud)

你会像以下一样使用它:

import static Reversed.reversed;

...

List<String> someStrings = getSomeStrings();
for (String s : reversed(someStrings)) {
    doSomethingWith(s);
}
Run Code Online (Sandbox Code Playgroud)

  • 这基本上是Google的Iterables.reverse所做的,是的:) (22认同)
  • 我知道有一个'规则'我们必须接受Jon的答案:)但是......我想接受这个(尽管它们本质上是相同的)因为它不需要我包含另一个第三方库(即使有人可能会说,这个理由打破了OO的一个主要优势 - 可重用性). (10认同)
  • Collections.reverse()不返回反向副本,但作为参数传递给它的List.但是,就像使用迭代器的解决方案一样.真的很优雅. (9认同)

Jon*_*eet 94

对于列表,您可以使用Google Guava库:

for (String item : Lists.reverse(stringList))
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

请注意,不会反转整个集合,或执行类似的任何操作 - 它只允许以相反的顺序进行迭代和随机访问.这比首先反转集合更有效.Lists.reverse

要反转任意迭代,您必须全部读取它,然后向后"重放"它.

(如果你还没有使用它,我会彻底建议你看看番石榴.这是伟大的东西.)

  • Iterables.reverse已被弃用,请改用Lists.reverse或ImmutableList.reverse. (23认同)
  • 他们已经更新了,这就是我所说的.他们只是没有释放它. (3认同)

小智 37

List(与Set不同)是一个有序集合,迭代它确实按合同保存订单.我原以为Stack会以相反的顺序迭代但不幸的是它没有.所以我能想到的最简单的解决方案是:

for (int i = stack.size() - 1; i >= 0; i--) {
    System.out.println(stack.get(i));
}
Run Code Online (Sandbox Code Playgroud)

我意识到这不是"每个"循环解决方案.我宁愿使用for循环而不是引入像Google Collections这样的新库.

Collections.reverse()也可以完成这项工作,但它会更新列表而不是以相反的顺序返回副本.

  • 这种方法可能适用于基于数组的列表(例如ArrayList),但对于链接列表来说它是次优的,因为每个get必须从每个get的开始到结束(或可能从end到start)遍历列表.最好在Nat的解决方案中使用更智能的迭代器(最适合List的所有实现). (3认同)

Phi*_*ibb 8

这会弄乱原始列表,也需要在循环外调用.此外,您不希望每次循环时都执行反向操作 - 如果其中一个Iterables.reverse ideas被应用,那么这是真的吗?

Collections.reverse(stringList);

for(String string: stringList){
//...do something
}
Run Code Online (Sandbox Code Playgroud)


Uri*_*Uri 5

AFAIK在标准库中没有标准的“ reverse_iterator”类东西支持for-each语法,这已经是他们后来引入该语言的语法糖。

您可以执行类似for(Item element:myList.clone()。reverse())的操作并支付相关价格。

这似乎与没有给您方便的方法执行昂贵的操作的明显现象是一致的-因为根据定义,列表可能具有O(N)随机访问的复杂性(您可以使用单链接实现接口),反向迭代最终可能是O(N ^ 2)。当然,如果您有ArrayList,则无需支付该价格。