Quel est le moyen le plus simple d'inverser cette ArrayList?
ArrayList 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());
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);
La méthode la plus simple pour inverser une ArrayList peut s’intéresser si vous êtes un fan de récursivité:
public ArrayList<Object> reverse(ArrayList<Object> list) {
if(list.size() > 1) {
Object value = list.remove(0);
reverse(list);
list.add(value);
}
return list;
}
Ou non-récursivement:
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;
}
Le truc ici est de définir "inverser". Vous pouvez modifier la liste en place, créer une copie dans l’ordre inverse ou créer une vue dans l’ordre inverse.
Le moyen le plus simple, intuitivement, est Collections.reverse
:
Collections.reverse(myList);
Cette méthode modifie la liste en place _. C'est-à-dire que Collections.reverse
prend la liste et écrase ses éléments, ne laissant aucune copie non révoquée. Cela convient à certains cas d'utilisation, mais pas à d'autres. de plus, cela suppose que la liste est modifiable. Si cela est acceptable, nous allons bien.
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 de parcourir la liste deux fois. Le constructeur de copie (new ArrayList<>(list)
) parcourt la liste, tout comme Collections.reverse
. Nous pouvons réécrire cette méthode pour itérer 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'API stream
de Java 8, qui certaines personnes trouve plus concise et lisible que ce qui précède:
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. que Collectors.toList()
fait très peu de garanties sur la liste de résultats. Si vous voulez vous assurer que le résultat est renvoyé sous la forme d'une ArrayList, utilisez plutôt Collectors.toCollection(ArrayList::new)
.
La troisième option consiste à créer une vue dans l'ordre inverse. C’est une solution plus compliquée et digne d’être approfondie/de sa propre question. La méthode Lists # reverse de Guava est un point de départ viable.
Le choix d'une implémentation "la plus simple" reste un exercice pour le lecteur.
Solution sans utiliser extra ArrayList ou une combinaison des méthodes add () et remove (). Les deux peuvent avoir un impact négatif si vous devez inverser une longue 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;
}
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));
}
Inverser une ArrayList de manière récursive 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;
}
}
Nous pouvons également faire la même chose 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;
}
Juste au cas où nous utilisons Java 8 , nous pouvons utiliser Stream. La liste de tableaux est une liste d'accès aléatoire et nous pouvons obtenir un flux d'éléments dans l'ordre inverse, puis le rassembler dans une nouvelle 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 ce n'est pas un accès aléatoire. Nous pouvons également utiliser instanceof
pour vérifier également.
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);
}
}
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;
}