Peut-on faire pour chaque boucle en java dans l'ordre inverse?
j'ai besoin de parcourir une liste dans l'ordre inverse en utilisant Java.
ainsi, où cela fait-il suivre:
for(String string: stringList){
//...do something
}
y a-t-il un moyen d'itérer la chaîne de caractères dans l'ordre inverse en utilisant le pour chaque syntaxe ?
pour plus de clarté: je sais comment itérer une liste dans l'ordre inverse mais je voudrais savoir (pour le bien de curiosity ) comment le faire dans le pour chaque style .
12 réponses
N'utilisez pas les Collections.méthode inverse il inverse en fait la liste originale en place. Si vous l'utilisez:
mauvaise direction!
Collections.reverse(new ArrayList(stringList))
pour éviter de modifier l'original, ceci renvoie une nouvelle liste avec les éléments de la liste originale copiés dans l'ordre inverse, et cela a O(n) les performances et les exigences d'espace en ce qui concerne la taille de la liste originale.
comme un plus solution efficace, vous pouvez écrire une classe qui présente une vue inversée d'une liste en tant que Générique itérable. L'itérateur retourné par votre classe utiliserait le ListIterator de la liste décorée pour marcher sur les éléments dans l'ordre inverse.
par exemple:
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);
}
}
et vous l'utilisez comme:
import static Reversed.reversed;
...
List<String> someStrings = getSomeStrings();
for (String s : reversed(someStrings)) {
doSomethingWith(s);
}
pour une liste, vous pouvez utiliser le Bibliothèque Google Guava :
for (String item : Lists.reverse(stringList))
{
// ...
}
noter que Lists.reverse
ne pas inverser la collection entière, ou faire quelque chose comme elle - il permet juste l'itération et l'accès aléatoire, dans l'ordre inverse. C'est plus efficace que d'inverser la collecte d'abord.
pour inverser une itérabilité arbitraire, il faut tout lire et puis "replay" à l'envers.
(si vous ne l'utilisez pas déjà, je minutieusement vous recommande d'avoir un oeil au Goyave . C'est un truc très.)
la liste (contrairement à L'ensemble) est une collection ordonnée et itérer sur elle ne préserve l'ordre par contrat. Je m'attendais à ce qu'une pile se répète dans l'ordre inverse, mais malheureusement ce n'est pas le cas. Donc la solution la plus simple à laquelle je peux penser est celle-ci:
for (int i = stack.size() - 1; i >= 0; i--) {
System.out.println(stack.get(i));
}
je me rends compte qu'il ne s'agit pas d'une solution" pour chaque " boucle. Je préfère utiliser la boucle for plutôt que d'introduire une nouvelle bibliothèque comme les collections Google.
Collections.inverser() aussi fait le travail, mais il met à jour la liste plutôt que de retourner une copie dans l'ordre inverse.
cela va interférer avec la liste originale et doit aussi être appelé en dehors de la boucle.
En outre, vous ne voulez pas effectuer une inversion chaque fois que vous bouclez-serait-ce vrai si l'un des Iterables.reverse ideas
a été appliquée?
Collections.reverse(stringList);
for(String string: stringList){
//...do something
}
AFAIK il n'y a pas une sorte de "réverse_iterator" standard dans la bibliothèque standard qui supporte la syntaxe pour-chaque qui est déjà un sucre syntaxique qu'ils ont apporté tard dans la langue.
Vous pourriez faire quelque chose comme(Élément de l'élément: maliste.clone.)(reverse()) et de payer le prix associé.
cela semble également assez cohérent avec le phénomène apparent de ne pas vous donner des moyens pratiques pour faire des opérations coûteuses-depuis une list, par définition, pourrait avoir O (N) la complexité d'accès aléatoire(vous pourriez implémenter l'interface avec un simple lien), l'itération inverse pourrait finir par être O (N^2). Bien sûr, si vous avez un ArrayList, vous ne payez pas ce prix.
ceci peut être une option. J'espère qu'il y a une meilleure façon de commencer à partir du dernier élément que de boucler la boucle jusqu'à la fin.
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);
}
}
à partir de le commentaire : vous devriez pouvoir utiliser Apache Commons ReverseListIterator
Iterable<String> reverse
= new IteratorIterable(new ReverseListIterator(stringList));
for(String string: reverse ){
//...do something
}
comme @rogerdpack a dit , vous devez envelopper le ReverseListIterator
comme un Iterable
.
pas sans écrire un code personnalisé qui vous donnera un recenseur qui inversera les éléments pour vous.
vous devriez pouvoir le faire en Java en créant une implémentation personnalisée de Iterable qui retournera les éléments dans l'ordre inverse.
ensuite, vous instanciez le wrapper (ou appelez la méthode, what-have-you) qui retournerait l'implémentation itérative qui inverse l'élément dans la boucle pour chaque boucle.
vous pouvez utiliser la classe de Collections http://java.sun.com/j2se/1.4.2/docs/api/java/util/Collections.html pour inverser la liste puis boucle.
Vous deviez annuler votre collection si vous souhaitez utiliser la syntaxe pour tout hors de la boîte et aller dans l'ordre inverse.
toutes les réponses ci-dessus remplissent seulement l'exigence, soit en enveloppant une autre méthode ou en appelant un code étranger à l'extérieur;
Voici la solution copiée du penser en Java 4ème édition , chapitre 11.13.1 Adaptermethodiom ;
voici le code:
// 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
*///:~
certainement une réponse tardive à cette question. Une possibilité est d'utiliser le ListIterator dans une boucle for. Ce n'est pas aussi propre que la syntaxe du côlon, mais ça marche.
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);
}
le crédit pour la syntaxe ListIterator va à "façons d'itérer sur une liste en Java"