Question

Je dois courir à travers une liste dans l'ordre inverse en utilisant Java.

Alors, où cela fait vers l'avant:

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

Y at-il un moyen de parcourir le stringList dans l'ordre inverse en utilisant la pour chaque syntaxe?

Pour plus de clarté. Je sais comment itérer une liste dans l'ordre inverse, mais je voudrais savoir (pour l'amour de la curiosité) comment le faire dans le pour chaque de style

Était-ce utile?

La solution

La méthode Collections.reverse retourne en fait une nouvelle liste avec les éléments de la liste d'origine copié en elle dans le sens inverse, de sorte que ce qui a des performances de O (n) en ce qui concerne la taille de la liste initiale.

En tant que solution plus efficace, vous pourriez écrire un décorateur qui présente une vue inverse d'une liste comme Iterable. Le itérateur retourné par votre décorateur utiliserait la ListIterator de la liste décorée de 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'utiliser comme:

import static Reversed.reversed;

...

List<String> someStrings = getSomeStrings();
for (String s : reversed(someStrings)) {
    doSomethingWith(s);
}

Autres conseils

Pour une liste, vous pouvez utiliser le Google Goyave Bibliothèque :

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

Notez que Lists.reverse ne pas inverser toute la collection, ou quoi que ce soit comme ça - il permet simplement itération et un accès aléatoire, dans l'ordre inverse. Ceci est plus efficace que l'inversion de la première collection.

Pour inverser une itérables arbitraire, vous auriez tout lire puis « rejouer » en arrière.

(Si vous n'êtes pas déjà l'utiliser, je bien vous recommande de jeter un oeil à la page Goyave . Il est grand genre de choses.)

La liste (à la différence du Set) est une collection et itérer ordonnée sur elle ne conserve l'ordre par contrat. Je me serais attendu à une pile à itérer dans l'ordre inverse, mais malheureusement, il ne fonctionne pas. Donc, la solution la plus simple que je peux penser est la suivante:

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

Je me rends compte que ce n'est pas un « pour chaque » solution en boucle. Je préfère utiliser la boucle que l'introduction d'une nouvelle bibliothèque comme les collections Google.

Collections.reverse () fait aussi le travail, mais il met à jour la liste plutôt que de retourner une copie dans l'ordre inverse.

gâchera avec la liste initiale et doit également être appelé en dehors de la boucle. Aussi, vous ne voulez pas effectuer une marche arrière à chaque fois que la boucle vous - serait-ce vrai si l'un des Iterables.reverse ideas a été appliqué

Collections.reverse(stringList);

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

AFAIK il n'y a pas une sorte de chose norme « reverse_iterator » dans la bibliothèque standard qui prend en charge la for-each syntaxe qui est déjà un sucre syntaxique qu'ils ont apporté jusque tard dans la langue.

Vous pouvez faire quelque chose comme pour (élément d'objet: myList.clone () inverse ().) Et de payer le prix associé.

Cela semble aussi 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 liste, par définition, pourrait avoir O (N) complexité d'accès aléatoire (vous pouvez implémenter l'interface avec une seule liaison ), 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.

Cela peut être une option. Hope il y a une meilleure façon de commencer à partir de dernier élément que de while 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);           
    }
}

de la commenter : Vous devriez pouvoir utiliser Apache Commons ReverseListIterator

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

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

@rogerdpack dit , vous avez besoin d'envelopper le ReverseListIterator comme Iterable.

Non sans écrire du code personnalisé qui vous donnera un recenseur qui inverse les éléments pour vous.

Vous devriez être en mesure de le faire en Java en créant une implémentation personnalisée de Iterable qui renverra les éléments dans l'ordre inverse.

Ensuite, vous instancierez l'enveloppe (ou appeler la méthode, ce que vous voudrez) qui renverrait la mise en œuvre Iterable qui inverse l'élément dans la boucle pour chaque.

Vous pouvez utiliser la classe Collections http : //java.sun.com/j2se/1.4.2/docs/api/java/util/Collections.html pour inverser la liste en boucle puis

.

Vous auriez besoin d'inverser votre collection si vous souhaitez utiliser la syntaxe pour chaque sortie de la boîte et aller dans l'ordre inverse.

Toutes les réponses ci-dessus ne satisfont à l'exigence, que ce soit en enroulant une autre méthode ou d'appeler un code étranger à l'extérieur;

Voici la solution copiée de la Penser à la 4ème édition Java , chapitre 11.13.1 AdapterMethodIdiom

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. Ce n'est pas aussi propre que la syntaxe du côlon, mais il fonctionne.

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); 
}
Crédit

pour la syntaxe ListIterator va

scroll top