web-dev-qa-db-ja.com

Javaの各ループに対して逆の順序で実行できますか?

Javaを使用して、リストを逆順に実行する必要があります。

したがって、これはどこに転送されますか:

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

for each構文を使用してstringListを逆の順序で繰り返す方法はありますか?

わかりやすくするために、リストを逆順で反復する方法を知っていますが、(好奇心のため)for eachスタイルでそれを行う方法を知りたいです。

140
Ron Tuffin

Collections.reverseメソッドは、実際には元のリストの要素が逆順にコピーされた新しいリストを返すため、元のリストのサイズに関してO(n)のパフォーマンスが得られます。

より効率的なソリューションとして、リストの逆のビューを反復可能として表示するデコレーターを作成できます。デコレータから返されたイテレータは、装飾されたリストの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);
}
147
Nat

リストについては、 Google Guava Library を使用できます。

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

Lists.reversedoes n'tはコレクション全体を元に戻す、またはそのようなことを行うことに注意してください-反復とランダムアクセスを許可するだけです。逆の順序で。これは、最初にコレクションを逆にするよりも効率的です。

任意のイテラブルを逆にするには、すべてを読んでから逆方向に「リプレイ」する必要があります。

(まだ使用していない場合は、を徹底的に参照してください Guava をご覧になることをお勧めします。もの。)

94
Jon Skeet

リストは(セットとは異なり)順序付けられたコレクションであり、それを反復処理することにより、契約ごとに順序が保持されます。 Stackが逆の順序で反復することを期待していましたが、残念ながらそうではありません。だから私が考えることができる最も簡単な解決策はこれです:

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

これは「for each」ループソリューションではないことを理解しています。 Googleコレクションのような新しいライブラリを導入するよりも、forループを使用したいです。

Collections.reverse()もジョブを実行しますが、逆順でコピーを返すのではなく、リストを更新します。

37
Gopi Reddy

これは元のリストを台無しにし、ループ外で呼び出す必要もあります。また、ループするたびに逆を実行したくない-Iterables.reverse ideasのいずれかが適用された場合、それは本当ですか?

Collections.reverse(stringList);

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

知る限りでは、標準ライブラリには、for-each構文をサポートする標準の「reverse_iterator」のようなものはありません。これは、すでに言語に導入された構文糖です。

For(Item element:myList.clone()。reverse())のようなことをして、関連する価格を支払うことができます。

これは、コストのかかる操作を行う便利な方法を提供しないという明らかな現象ともかなり一貫しているようです。リストは、定義により、O(N)ランダムアクセスの複雑さを伴う可能性があるためです(シングルリンク)、逆反復はO(N ^ 2)になる可能性があります。もちろん、ArrayListをお持ちの場合は、その価格を支払う必要はありません。

5
Uri

これはオプションかもしれません。 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);           
    }
}
2
Krishna

コメント 現在:Apache Commonsを使用できるはずです ReverseListIterator

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

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

@ rogerdpackが言った のように、ReverseListIteratorIterableとしてラップする必要があります。

2
serv-inc

要素を逆にする列挙子を提供するカスタムコードを書かずに。

要素を逆順で返すIterableのカスタム実装を作成することにより、Javaで実行できるはずです。

次に、ラッパーをインスタンス化して(または、メソッドwhat-have-youを呼び出して)、ループごとに要素を反転するIterable実装を返します。

1
casperOne

Collectionsクラス http://Java.Sun.com/j2se/1.4.2/docs/api/Java/util/Collections.html を使用して、リストを逆にしてループすることができます。

1
Allan

すぐに使用できるfor each構文を使用し、逆の順序にする場合は、コレクションを逆にする必要があります。

1
Owen

上記のすべての回答は、別のメソッドをラップするか、外部コードを呼び出すことにより、要件を満たしているだけです。

Thinking in Java 4th edition、Chapter 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
*///:~
1
qiwen li

この質問に対する間違いなく遅い答え。 1つの可能性は、forItループで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でリストを反復処理する方法"

0
ScottMichaud