Java を使用して逆の順序でリストを実行する必要があります。
したがって、これはどこに転送されますか:
for(String string: stringList){
//...do something
}
for each構文を使用して stringList を逆順に繰り返す方法はありますか?
明確にするために:リストを逆の順序で反復する方法を知っていますが、(好奇心のために)for eachスタイルでそれを行う方法を知りたいです。
Collections.reverse メソッドは実際には、元のリストの要素が逆順にコピーされた新しいリストを返すため、元のリストのサイズに関して 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);
}
リストについては、 Google Guava Libraryを使用できます。
for (String item : Lists.reverse(stringList))
{
// ...
}
コレクション全体を逆にしたり、そのようなことをしたりしないことに注意してください-逆の順序で反復とランダムアクセスを許可するだけです。これは、最初にコレクションを逆にするよりも効率的です。Lists.reverse
任意のイテラブルを逆にするには、すべてを読み取ってから逆方向に「再生」する必要があります。
(まだ使用していない場合は、 Guavaを確認することを強くお勧めします。これは素晴らしいものです。)
リスト(セットとは異なり)は順序付けられたコレクションであり、リストを反復処理すると、契約による順序が保持されます。スタックが逆の順序で繰り返されることを期待していましたが、残念ながらそうではありません。だから私が考えることができる最も簡単な解決策はこれです:
for (int i = stack.size() - 1; i >= 0; i--) {
System.out.println(stack.get(i));
}
これは「foreach」ループソリューションではないことを理解しています。Googleコレクションのような新しいライブラリを導入するよりもforループを使用したいと思います。
Collections.reverse()もその役割を果たしますが、逆の順序でコピーを返すのではなく、リストを更新します。
これは元のリストを台無しにし、ループの外でも呼び出す必要があります。また、ループするたびにリバースを実行したくありません-いずれIterables.reverse ideas
かが適用された場合、それは本当ですか?
Collections.reverse(stringList);
for(String string: stringList){
//...do something
}
私の知る限り、標準ライブラリには、言語に遅れて導入された構文糖衣である for-each 構文をサポートする標準的な「reverse_iterator」のようなものはありません。
for(Item element: myList.clone().reverse()) のようなことをして、関連する価格を支払うことができます。
これはまた、高価な操作を行うための便利な方法を提供しないという明らかな現象とかなり一致しているようです.反復は最終的に O(N^2) になる可能性があります。もちろん、ArrayList がある場合は、その代価を支払う必要はありません。
コメントの時点で:Apache Commonsを使用できるはずですReverseListIterator
Iterable<String> reverse
= new IteratorIterable(new ReverseListIterator(stringList));
for(String string: reverse ){
//...do something
}
@rogerdpack が言ったように、 をとしてラップReverseListIterator
する必要がありますIterable
。
Roland Nordborg -Løvstad がコメントで推奨しているように、現在の Java でラムダを使用して簡素化できます。
Iterable<String> reverse = () -> new ReverseListIterator<>(stringList)
これはオプションかもしれません。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);
}
}
要素を逆にする列挙子を提供するカスタムコードを書かないわけではありません。
要素を逆の順序で返す Iterable のカスタム実装を作成することにより、Java でそれを実行できるはずです。
次に、 for each ループ内の要素を逆にする Iterable 実装を返すラッパーをインスタンス化します (またはメソッド what-have-you を呼び出します)。
Collectionsクラスを使用して、リストを逆にしてループすることができます。
for each 構文をすぐに使用して逆の順序で使用する場合は、コレクションを逆にする必要があります。
上記のすべての回答は、別のメソッドをラップするか、外部コードを呼び出すことによって、要件を満たすだけです。
Thinking in Java 第 4 版の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
*///:~