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

时间:2009-07-08 13:34:08

标签: java reverse foreach

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

所以这是前进的地方:

for(String string: stringList){
//...do something
}

是否有某种方法可以使用每个语法的以相反的顺序迭代stringList?

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

14 个答案:

答案 0 :(得分:145)

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

错误的方式!

Collections.reverse(new ArrayList(stringList))

为了避免修改原始文件,这将返回一个新列表,其中原始列表的元素以相反的顺序复制到其中,并且对原始列表的大小具有O(n)性能和空间要求。 / p>

作为一种更有效的解决方案,您可以编写一个类,将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);
}

答案 1 :(得分:93)

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

for (String item : Lists.reverse(stringList))
{
    // ...
}

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

要反转任意迭代,你必须全部阅读,然后向后“重播”它。

(如果您还没有使用它,我彻底建议您查看Guava。这很棒。)

答案 2 :(得分:36)

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

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

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

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

答案 3 :(得分:8)

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

Collections.reverse(stringList);

for(String string: stringList){
//...do something
}

答案 4 :(得分:5)

AFAIK标准库中没有标准的“reverse_iterator”类型的东西支持for-each语法,这种语法已经是他们在语言中迟到的语法糖。

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

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

答案 5 :(得分:2)

这可能是一种选择。希望有一种更好的方法从最后一个元素开始,而不是从循环到结束。

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);           
    }
}

答案 6 :(得分:2)

the comment开始:您应该可以使用Apache Commons ReverseListIterator

Iterable<String> reverse 
    = new IteratorIterable(new ReverseListIterator(stringList));

for(String string: reverse ){
    //...do something
}

作为@rogerdpack said,您需要将ReverseListIterator包装为Iterable

答案 7 :(得分:1)

并非没有编写一些自定义代码,它会为您提供一个枚举器,它将为您反转元素。

您应该能够通过创建Iterable的自定义实现来在Java中完成它,它将以相反的顺序返回元素。

然后,您将实例化包装器(或调用方法,有什么用),它将返回Iterable实现,该实现反转for循环中的元素。

答案 8 :(得分:1)

您可以使用Collections类http://java.sun.com/j2se/1.4.2/docs/api/java/util/Collections.html来反转列表然后循环。

答案 9 :(得分:1)

如果您想使用开箱即用的for each语法并按相反的顺序进行操作,则需要撤消您的收藏。

答案 10 :(得分:1)

以上所有答案只能通过包装另一种方法或在外面调用一些外国代码来满足要求;

以下是从 Thinking in Java 4th edition 复制的解决方案,第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
*///:~

答案 11 :(得分:0)

肯定是这个问题的最新答案。一种可能性是在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语法的信用额度转到"Ways to iterate over a list in Java"

答案 12 :(得分:0)

解决方法:

Collections.reverse(stringList).forEach(str -> ...);

或使用guava

Lists.reverse(stringList).forEach(str -> ...);

答案 13 :(得分:0)

例如

Integer[][] a = {
                { 1, 2, 3 }, 
                { 4, 5, 6 }, 
                { 9, 8, 9 }, 
                };

List<List<Integer>> arr = Arrays.stream(a)
                .map(Arrays::asList)
                .collect(Collectors.toList());

现在反转。

Collections.reverse(arr);
System.out.println("Reverse Array" + arr);
for (List<Integer> obj : arr) {
    // TODO
}