Quelle est la manière la plus simple d'inverser une liste de tableaux?

334

Quelle est la manière la plus simple d'inverser cette ArrayList?

ArrayList<Integer> aList = new ArrayList<>();

//Add elements to ArrayList object
aList.add("1");
aList.add("2");
aList.add("3");
aList.add("4");
aList.add("5");

while (aList.listIterator().hasPrevious())
  Log.d("reverse", "" + aList.listIterator().previous());
Ishu
la source

Réponses:

799
Collections.reverse(aList);

Exemple ( référence ):

ArrayList aList = new ArrayList();
//Add elements to ArrayList object
aList.add("1");
aList.add("2");
aList.add("3");
aList.add("4");
aList.add("5");
Collections.reverse(aList);
System.out.println("After Reverse Order, ArrayList Contains : " + aList);
Shankar Agarwal
la source
2
@AgarwalShankar j'obtiens une erreur requise ArrayList trouvé nul. Suis-je en train de manquer quelque chose.
Sagar Devanga
9
@SagarDevanga La liste est inversée sur place, pas retournée.
Carcigenicate
Collections.reverse (Liste); Je l'ai utilisé dans un projet Android, ça marche bien.
Damir Varevac
22

Ce n'est pas le moyen le plus simple, mais si vous êtes un fan de la récursivité, vous pourriez être intéressé par la méthode suivante pour inverser une ArrayList:

public ArrayList<Object> reverse(ArrayList<Object> list) {
    if(list.size() > 1) {                   
        Object value = list.remove(0);
        reverse(list);
        list.add(value);
    }
    return list;
}

Ou de façon non récursive:

public ArrayList<Object> reverse(ArrayList<Object> list) {
    for(int i = 0, j = list.size() - 1; i < j; i++) {
        list.add(i, list.remove(j));
    }
    return list;
}
Todd
la source
Je peux me tromper, mais dans votre exemple non récursif, n'est-il pas int jmis à jour à chaque itération? Vous l'initialisez à j = list.size() - 1mais je ne pense pas que la section d' initialisation du for loopsoit mise à jour à chaque itération, n'est-ce pas?
Tony Chan
@Turbo j n'a pas besoin d'être mis à jour à chaque itération. Il est initialisé sur le dernier index de ArrayList et est utilisé pour accéder au dernier élément. À l'intérieur de la boucle for, le dernier élément est supprimé et inséré dans l'index i; i est incrémenté jusqu'à ce qu'il atteigne l'avant-dernière position dans ArrayList.
todd
1
Oui, mais à la deuxième itération, n'obtiendrez-vous pas un IndexOutOfBoundsExceptionpuisque vous essayez d'accéder au j(dernier index de la liste de tableaux d'origine) mais vous avez déjà supprimé l'objet à cet index?
Tony Chan
1
Désolé, vient d'exécuter le code, fonctionne définitivement. J'ai oublié que cela add()pousse les autres éléments dans le tableau, donc le tableau reste essentiellement une taille constante. Des solutions intéressantes, merci!
Tony Chan
Aussi, juste curieux, mais comment avez-vous trouvé la méthode récursive? Je ne pense pas que c'est quelque chose auquel je penserais normalement.
Tony Chan
13

L'astuce consiste ici à définir «inverse». On peut modifier la liste en place, créer une copie dans l'ordre inverse ou créer une vue dans l'ordre inverse.

La manière la plus simple, intuitivement parlant , est Collections.reverse:

Collections.reverse(myList);

Cette méthode modifie la liste en place . Autrement dit, Collections.reverseprend la liste et écrase ses éléments, ne laissant aucune copie non inversée derrière. Cela convient à certains cas d'utilisation, mais pas à d'autres; en outre, il suppose que la liste est modifiable. Si cela est acceptable, nous sommes bons.


Sinon, on pourrait créer une copie dans l'ordre inverse :

static <T> List<T> reverse(final List<T> list) {
    final List<T> result = new ArrayList<>(list);
    Collections.reverse(result);
    return result;
}

Cette approche fonctionne, mais nécessite une itération sur la liste deux fois. Le constructeur de copie ( new ArrayList<>(list)) parcourt la liste, et il en est de même Collections.reverse. Nous pouvons réécrire cette méthode pour répéter une seule fois, si nous sommes si enclins:

static <T> List<T> reverse(final List<T> list) {
    final int size = list.size();
    final int last = size - 1;

    // create a new list, with exactly enough initial capacity to hold the (reversed) list
    final List<T> result = new ArrayList<>(size);

    // iterate through the list in reverse order and append to the result
    for (int i = last; i >= 0; --i) {
        final T element = list.get(i);
        result.add(element);
    }

    // result now holds a reversed copy of the original list
    return result;
}

C'est plus efficace, mais aussi plus verbeux.

Alternativement, nous pouvons réécrire ce qui précède pour utiliser l' streamAPI de Java 8 , que certaines personnes trouvent plus concise et lisible que ci-dessus:

static <T> List<T> reverse(final List<T> list) {
    final int last = list.size() - 1;
    return IntStream.rangeClosed(0, last) // a stream of all valid indexes into the list
        .map(i -> (last - i))             // reverse order
        .mapToObj(list::get)              // map each index to a list element
        .collect(Collectors.toList());    // wrap them up in a list
}

nb. cela Collectors.toList()fait très peu de garanties sur la liste des résultats. Si vous voulez vous assurer que le résultat revient en tant que ArrayList, utilisez Collectors.toCollection(ArrayList::new)plutôt.


La troisième option consiste à créer une vue dans l'ordre inverse . Il s'agit d'une solution plus compliquée, et mérite une lecture plus approfondie / sa propre question. La méthode inverse des listes de goyaves est un point de départ viable.

Le choix d'une implémentation "la plus simple" est laissé comme un exercice pour le lecteur.

naomimyselfandi
la source
6

Solution sans utiliser ArrayList supplémentaire ou une combinaison de méthodes add () et remove (). Les deux peuvent avoir un impact négatif si vous devez inverser une énorme liste.

 public ArrayList<Object> reverse(ArrayList<Object> list) {

   for (int i = 0; i < list.size() / 2; i++) {
     Object temp = list.get(i);
     list.set(i, list.get(list.size() - i - 1));
     list.set(list.size() - i - 1, temp);
   }

   return list;
 }
contrapost
la source
5
ArrayList<Integer> myArray = new ArrayList<Integer>();

myArray.add(1);
myArray.add(2);
myArray.add(3);

int reverseArrayCounter = myArray.size() - 1;

for (int i = reverseArrayCounter; i >= 0; i--) {
    System.out.println(myArray.get(i));
}
Tolunay Guney
la source
2

Inverser une ArrayList de manière récursive et sans créer de nouvelle liste pour ajouter des éléments:

   public class ListUtil {

    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<String>();
        arrayList.add("1");
        arrayList.add("2");
        arrayList.add("3");
        arrayList.add("4");
        arrayList.add("5");
        System.out.println("Reverse Order: " + reverse(arrayList));

    }

    public static <T> List<T> reverse(List<T> arrayList) {
        return reverse(arrayList,0,arrayList.size()-1);
    }
    public static <T> List<T> reverse(List<T> arrayList,int startIndex,int lastIndex) {

        if(startIndex<lastIndex) {
            T t=arrayList.get(lastIndex);
            arrayList.set(lastIndex,arrayList.get(startIndex));
            arrayList.set(startIndex,t);
            startIndex++;
            lastIndex--;
            reverse(arrayList,startIndex,lastIndex);
        }
        return arrayList;
    }

}
Joby Wilson Mathews
la source
1

Au cas où nous utilisons Java 8 , nous pouvons utiliser Stream. L'ArrayList est une liste d'accès aléatoire et nous pouvons obtenir un flux d'éléments dans l'ordre inverse, puis le collecter dans un nouveau ArrayList.

public static void main(String[] args) {
        ArrayList<String> someDummyList = getDummyList();
        System.out.println(someDummyList);
        int size = someDummyList.size() - 1;
        ArrayList<String> someDummyListRev = IntStream.rangeClosed(0,size).mapToObj(i->someDummyList.get(size-i)).collect(Collectors.toCollection(ArrayList::new));
        System.out.println(someDummyListRev);
    }

    private static ArrayList<String> getDummyList() {
        ArrayList dummyList = new ArrayList();
        //Add elements to ArrayList object
        dummyList.add("A");
        dummyList.add("B");
        dummyList.add("C");
        dummyList.add("D");
        return dummyList;
    }

L'approche ci-dessus ne convient pas à LinkedList car il ne s'agit pas d'un accès aléatoire. Nous pouvons également utiliser instanceofpour vérifier également.

akhil_mittal
la source
1

Nous pouvons également faire de même avec java 8.

public static<T> List<T> reverseList(List<T> list) {
        List<T> reverse = new ArrayList<>(list.size());

        list.stream()
                .collect(Collectors.toCollection(LinkedList::new))
                .descendingIterator()
                .forEachRemaining(reverse::add);

        return reverse;
    }
vijayraj34
la source
0

Un peu plus lisible :)

public static <T> ArrayList<T> reverse(ArrayList<T> list) {
    int length = list.size();
    ArrayList<T> result = new ArrayList<T>(length);

    for (int i = length - 1; i >= 0; i--) {
        result.add(list.get(i));
    }

    return result;
}
Oui
la source
0

Une autre solution récursive

 public static String reverse(ArrayList<Float> list) {
   if (list.size() == 1) {
       return " " +list.get(0);
   }
   else {
       return " "+ list.remove(list.size() - 1) + reverse(list);
   } 
 }
dt94
la source