Sztuczka polega na zdefiniowaniu „odwrotności”. Można zmodyfikować listę w miejscu, utworzyć kopię w odwrotnej kolejności lub utworzyć widok w odwrotnej kolejności.
Najprostszym, intuicyjnie mówiąc , jest Collections.reverse
:
Collections.reverse(myList);
Ta metoda modyfikuje listę na miejscu . Oznacza to, że Collections.reverse
pobiera listę i zastępuje jej elementy, nie pozostawiając żadnej nieodwróconej kopii. Jest to odpowiednie w niektórych przypadkach użycia, ale nie w innych; ponadto zakłada, że lista jest modyfikowalna. Jeśli jest to do zaakceptowania, jesteśmy dobrzy.
Jeśli nie, można utworzyć kopię w odwrotnej kolejności :
static <T> List<T> reverse(final List<T> list) {
final List<T> result = new ArrayList<>(list);
Collections.reverse(result);
return result;
}
To podejście działa, ale wymaga dwukrotnego iterowania listy. Konstruktor kopiowania ( new ArrayList<>(list)
) wykonuje iterację po liście, podobnie jak Collections.reverse
. Możemy przepisać tę metodę, aby iterować tylko raz, jeśli jesteśmy tak skłonni:
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;
}
Jest to bardziej wydajne, ale także bardziej szczegółowe.
Alternatywnie możemy przepisać powyższe, aby użyć stream
interfejsu API języka Java 8 , które niektórzy uważają za bardziej zwięzłe i czytelne niż powyższe:
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. który Collectors.toList()
sprawia, że bardzo niewiele gwarancji o liście wynikowej. Jeśli chcesz mieć pewność, że wynik wróci jako ArrayList, użyj Collectors.toCollection(ArrayList::new)
zamiast tego.
Trzecią opcją jest utworzenie widoku w odwrotnej kolejności . Jest to bardziej skomplikowane rozwiązanie i warte dalszego czytania / własnego pytania. Guava za Listy # odwrotna metoda jest dobrym punktem wyjścia.
Wybór „najprostszej” implementacji pozostawia czytelnikowi ćwiczenie.