¿Cuál es la forma más sencilla de invertir una ArrayList?

Resuelto Ishu asked hace 54 años • 13 respuestas

¿Cuál es la forma más sencilla de revertir este 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 avatar Jan 01 '70 08:01 Ishu
Aceptado
Collections.reverse(aList);

Ejemplo ( Referencia ):

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 avatar May 26 '2012 13:05 Shankar Agarwal

El truco aquí es definir "inversa". Se puede modificar la lista en su lugar, crear una copia en orden inverso o crear una vista en orden inverso.

La forma más sencilla, intuitivamente hablando , es Collections.reverse:

Collections.reverse(myList);

Este método modifica la lista existente . Es decir, Collections.reversetoma la lista y sobrescribe sus elementos, sin dejar ninguna copia sin revertir. Esto es adecuado para algunos casos de uso, pero no para otros; además, supone que la lista es modificable. Si esto es aceptable, estamos bien.


De lo contrario, se podría crear una copia en orden inverso :

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

Este enfoque funciona, pero requiere repetir la lista dos veces. El constructor de copia ( new ArrayList<>(list)) itera sobre la lista y también lo hace Collections.reverse. Podemos reescribir este método para iterar solo una vez, si así lo deseamos:

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;
}

Esto es más eficiente, pero también más detallado.

Alternativamente, podemos reescribir lo anterior para usar streamla API de Java 8, que algunas personas encuentran más concisa y legible que lo anterior:

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
}

nótese bien. eso Collectors.toList()ofrece muy pocas garantías sobre la lista de resultados. Si desea asegurarse de que el resultado regrese como ArrayList, use Collectors.toCollection(ArrayList::new)en su lugar.


La tercera opción es crear una vista en orden inverso . Esta es una solución más complicada y merece una lectura adicional/su propia pregunta. El método Lists#reverse de Guava es un punto de partida viable.

La elección de la implementación "más simple" se deja como ejercicio para el lector.

naomimyselfandi avatar Sep 19 '2017 16:09 naomimyselfandi