Cómo obtener el último valor de una ArrayList

597

¿Cómo puedo obtener el último valor de una ArrayList?

No sé el último índice de ArrayList.

Jessy
fuente
164
Voté esta pregunta, porque me preguntaba por qué no existe un método como: getLastItem () y vine a ver si había una respuesta. list.size () - 1 no es bonito.
Nuno Gonçalves
2
@ NunoGonçalves ¡Siempre puedes subclasificarlo!
Tim
12
Siempre puede usar una LinkedList que tiene el métodogetLast()
ssedano
66
Listado vinculado agrega un montón de gastos generales. Use Guava como se muestra a continuación: lastElement = Iterables.getLast (iterableList); O simplemente indexe una llamada get () con size () - 1. No es tan feo en comparación con el uso de una lista vinculada cuando no es necesario. Las advertencias habituales se aplican con respecto a las condiciones de excepción; consulte ArrayList javadoc
RichieHH
10
Usar list.size () -1 no es bonito, pero usar una API de terceros solo para esto es peor
Javo

Respuestas:

692

Lo siguiente es parte de la Listinterfaz (que implementa ArrayList):

E e = list.get(list.size() - 1);

Ees el tipo de elemento Si la lista está vacía, getarroja un IndexOutOfBoundsException. Puede encontrar toda la documentación de la API aquí .

Johannes Schaub - litb
fuente
55
¿Causará esto una iteración de la lista? Eso no me parece muy eficiente. Vengo de C ++, donde hay métodos front () y back () reales en el objeto de la lista, que se implementan internamente con referencias de cabeza y cola. ¿Hay un mecanismo similar en Java?
Brady
26
No funcionará qué pasa si la lista está vacía, list.size () devolverá 0. y terminará con list.get (-1);
FRR
18
@feresr eh. Quiere obtener el último valor en la lista. Por supuesto, eso implica que size () es> 0. Eso sería cierto para cualquier tipo de implementación. Leer hasta el final habría ahorrado el tiempo que necesitabas para escribir tu comentario y mi tiempo para responder :) Mi respuesta dice al final "Si la lista está vacía, obtén una excepción IndexOutOfBoundsException"
Johannes Schaub - litb
16
@Brady no causará una iteración O (n) para una ArrayList, porque como puedes adivinar, está respaldada por una matriz. Entonces, un simple get (<índice>) solo resulta en una recuperación de tiempo constante de una matriz. (La fuente JDK confirma esto) Para otras implementaciones de listas, esto no está garantizado, por ejemplo, LinkedList tiene un método getLast () que es de tiempo constante.
Peter
99
No puedo entender por qué decidieron implementar un lastElement()método simple para ellos Vectorpero no para ellos ArrayList. ¿Qué pasa con esa inconsistencia?
Stefan Dimitrov
211

No hay una manera elegante en Java vainilla.

Google guayaba

La biblioteca de Google Guava es excelente, echa un vistazo a su Iterablesclase . Este método arrojará un NoSuchElementExceptionsi la lista está vacía, en lugar de un IndexOutOfBoundsException, como con el size()-1enfoque típico : encuentro NoSuchElementExceptionmucho mejor o la capacidad de especificar un valor predeterminado:

lastElement = Iterables.getLast(iterableList);

También puede proporcionar un valor predeterminado si la lista está vacía, en lugar de una excepción:

lastElement = Iterables.getLast(iterableList, null);

o, si está usando Opciones:

lastElementRaw = Iterables.getLast(iterableList, null);
lastElement = (lastElementRaw == null) ? Option.none() : Option.some(lastElementRaw);
Antony Stubbs
fuente
3
¿Sabes si este método hace un recorrido lineal por la lista para encontrar el último elemento?
BillMan
55
@BillMan En el caso de HashSet sí, en el caso de ArrayList no.
Simon
66
Debe agregar esa Iterables.getLastverificación si RandomAccessse implementa y, por lo tanto, si se accede al elemento en O (1).
Karl Richter
1
En lugar de Option, puede usar el Java nativo Optional. También será un poco más limpio: lastElement = Optional.ofNullable(lastElementRaw);.
Little Helper
186

esto debería hacerlo:

if (arrayList != null && !arrayList.isEmpty()) {
  T item = arrayList.get(arrayList.size()-1);
}
Henrik Paul
fuente
29
¿No hay una forma elegante de hacerlo? : /
kommradHomer
66
Probablemente al menos deberías demostrar la asignación ... ArrayList.get es libre de efectos secundarios.
Antony Stubbs
¿Es demasiado insignificante indicar que lo anterior no asigna / devuelve nada?
Brian Agnew
Si una ArrayList solo tiene un registro, se produce una excepción. ¿Cuál será la solución?
hasnain_ahmad
2
@hasnain_ahmad, cuando ArraList tiene 1 elemento, funciona correctamente, debe preocuparse por ArrayList y ArrayList no inicializados con registro cero. Y esta respuesta maneja ambos casos
Farid
27

Uso la clase micro-util para obtener el último (y primer) elemento de la lista:

public final class Lists {

    private Lists() {
    }

    public static <T> T getFirst(List<T> list) {
        return list != null && !list.isEmpty() ? list.get(0) : null;
    }

    public static <T> T getLast(List<T> list) {
        return list != null && !list.isEmpty() ? list.get(list.size() - 1) : null;
    }
}

Ligeramente más flexible:

import java.util.List;

/**
 * Convenience class that provides a clearer API for obtaining list elements.
 */
public final class Lists {

  private Lists() {
  }

  /**
   * Returns the first item in the given list, or null if not found.
   *
   * @param <T> The generic list type.
   * @param list The list that may have a first item.
   *
   * @return null if the list is null or there is no first item.
   */
  public static <T> T getFirst( final List<T> list ) {
    return getFirst( list, null );
  }

  /**
   * Returns the last item in the given list, or null if not found.
   *
   * @param <T> The generic list type.
   * @param list The list that may have a last item.
   *
   * @return null if the list is null or there is no last item.
   */
  public static <T> T getLast( final List<T> list ) {
    return getLast( list, null );
  }

  /**
   * Returns the first item in the given list, or t if not found.
   *
   * @param <T> The generic list type.
   * @param list The list that may have a first item.
   * @param t The default return value.
   *
   * @return null if the list is null or there is no first item.
   */
  public static <T> T getFirst( final List<T> list, final T t ) {
    return isEmpty( list ) ? t : list.get( 0 );
  }

  /**
   * Returns the last item in the given list, or t if not found.
   *
   * @param <T> The generic list type.
   * @param list The list that may have a last item.
   * @param t The default return value.
   *
   * @return null if the list is null or there is no last item.
   */
  public static <T> T getLast( final List<T> list, final T t ) {
    return isEmpty( list ) ? t : list.get( list.size() - 1 );
  }

  /**
   * Returns true if the given list is null or empty.
   *
   * @param <T> The generic list type.
   * @param list The list that has a last item.
   *
   * @return true The list is empty.
   */
  public static <T> boolean isEmpty( final List<T> list ) {
    return list == null || list.isEmpty();
  }
}
usuario11153
fuente
8
Solo usa guayaba. No vuelva a inventar
haga clic en Votación a favor el
15
@ClickUpvote Usar guayaba para un solo método pequeño es en muchos casos una exageración. Mi respuesta es para personas que buscan una solución Java vainilla . Si ya está utilizando Guava en su proyecto, vea otra respuesta para la solución basada en Guava.
user11153
55
Si no usa guayaba, termina escribiendo muchas clases de utilidades como esta.
Haga clic en Upvote el
66
A veces, obtener permiso para agregar una biblioteca de terceros puede ser mucho más complicado que agregar una sola clase Java nativa. Por ejemplo, los contratos gubernamentales donde limitan y seleccionan bibliotecas de terceros.
Dave Jarvis
2
isEmptyno comprueba si la lista está vacía y, por lo tanto, debería estar, isNullOrEmptyy eso no es parte de la pregunta, ya sea que intente mejorar el conjunto de respuestas o le proporcione clases de utilidad (que son una reinvención).
Karl Richter
10

El size()método devuelve el número de elementos en ArrayList. Los valores de índice de los elementos están 0completos (size()-1), por lo que usaría myArrayList.get(myArrayList.size()-1)para recuperar el último elemento.

Ken Paul
fuente
6

Usando lambdas:

Function<ArrayList<T>, T> getLast = a -> a.get(a.size() - 1);
Luis Vieira Damiani
fuente
6

No hay una forma elegante de obtener el último elemento de una lista en Java (en comparación, por ejemplo, items[-1]en Python).

Tienes que usar list.get(list.size()-1).

Cuando se trabaja con listas obtenidas por llamadas a métodos complicados, la solución reside en la variable temporal:

List<E> list = someObject.someMethod(someArgument, anotherObject.anotherMethod());
return list.get(list.size()-1);

Esta es la única opción para evitar versiones feas y a menudo caras o incluso que no funcionan:

return someObject.someMethod(someArgument, anotherObject.anotherMethod()).get(
    someObject.someMethod(someArgument, anotherObject.anotherMethod()).size() - 1
);

Sería bueno si la solución para este defecto de diseño se introdujera en la API de Java.

Tregoreg
fuente
No veo una "falla de diseño" aquí, lo que mencionas es un caso de uso raro que no vale la pena agregar a la Listinterfaz. ¿Por qué querría llamar a un método que devuelve una Lista, si solo le interesa el último elemento? No recuerdo haberlo visto antes.
Dorian Gray
1
@DorianGray Leer el último elemento de una lista es una operación bastante común y list.get(list.size()-1)es el ejemplo mínimo que muestra el problema. Estoy de acuerdo en que los ejemplos "avanzados" pueden ser controvertidos y posiblemente un caso marginal, solo quería mostrar cómo el problema puede propagarse aún más. Supongamos que la clase de someObjectes extranjera, proveniente de una biblioteca externa.
Tregoreg
No veo dónde es esto bastante común, y si lo es, será mejor que lo uses ArrayDeque.
Dorian Gray
@DorianGray Esta pregunta tiene muchos votos a favor y puntos de vista, por lo que hay muchas personas interesadas en obtener el último valor de un ArrayList.
Tregoreg
5

Si puede, cambie el ArrayListpor un ArrayDeque, que tiene métodos convenientes como removeLast.

John Glassmyer
fuente
1
Esto significa al menos un costo lineal en comparación con el costo constante para el acceso directo, pero vale la pena mencionarlo.
Karl Richter
@KarlRichter Sí. Esto corresponde con la ausencia de métodos como get (int) en la interfaz de ArrayDeque. Esto es lo que quise sugerir por "Si puedes"; si el índice no está accediendo a la lista, entonces tal vez no sea necesario que sea una Lista.
John Glassmyer
3

Como se indica en la solución, si el Listestá vacío, IndexOutOfBoundsExceptionse arroja un. Una mejor solución es usar el Optionaltipo:

public class ListUtils {
    public static <T> Optional<T> last(List<T> list) {
        return list.isEmpty() ? Optional.empty() : Optional.of(list.get(list.size() - 1));
    }
}

Como era de esperar, el último elemento de la lista se devuelve como Optional:

var list = List.of(10, 20, 30);
assert ListUtils.last(list).orElse(-1) == 30;

También trata con gracia las listas vacías:

var emptyList = List.<Integer>of();
assert ListUtils.last(emptyList).orElse(-1) == -1;
Colin Breame
fuente
2

Si utiliza una LinkedList en su lugar, puede acceder al primer elemento y al último con solo getFirst()y getLast()(si desea una forma más limpia que size () -1 y get (0))

Implementación

Declarar una lista enlazada

LinkedList<Object> mLinkedList = new LinkedList<>();

Entonces estos son los métodos que puede utilizar para obtener lo que desea, en este caso estamos hablando del elemento PRIMERO y ÚLTIMO de una lista

/**
     * Returns the first element in this list.
     *
     * @return the first element in this list
     * @throws NoSuchElementException if this list is empty
     */
    public E getFirst() {
        final Node<E> f = first;
        if (f == null)
            throw new NoSuchElementException();
        return f.item;
    }

    /**
     * Returns the last element in this list.
     *
     * @return the last element in this list
     * @throws NoSuchElementException if this list is empty
     */
    public E getLast() {
        final Node<E> l = last;
        if (l == null)
            throw new NoSuchElementException();
        return l.item;
    }

    /**
     * Removes and returns the first element from this list.
     *
     * @return the first element from this list
     * @throws NoSuchElementException if this list is empty
     */
    public E removeFirst() {
        final Node<E> f = first;
        if (f == null)
            throw new NoSuchElementException();
        return unlinkFirst(f);
    }

    /**
     * Removes and returns the last element from this list.
     *
     * @return the last element from this list
     * @throws NoSuchElementException if this list is empty
     */
    public E removeLast() {
        final Node<E> l = last;
        if (l == null)
            throw new NoSuchElementException();
        return unlinkLast(l);
    }

    /**
     * Inserts the specified element at the beginning of this list.
     *
     * @param e the element to add
     */
    public void addFirst(E e) {
        linkFirst(e);
    }

    /**
     * Appends the specified element to the end of this list.
     *
     * <p>This method is equivalent to {@link #add}.
     *
     * @param e the element to add
     */
    public void addLast(E e) {
        linkLast(e);
    }

Entonces, puedes usar

mLinkedList.getLast(); 

para obtener el último elemento de la lista.

Gastón Saillén
fuente
1

la guayaba proporciona otra forma de obtener el último elemento de a List:

last = Lists.reverse(list).get(0)

si la lista proporcionada está vacía, arroja un IndexOutOfBoundsException

pero_hero
fuente
1
java.util.Collections#reverselo hace también
RoBeaToZ
1
@RoBeaToZ, lo hace, pero cambia la lista original al iterar a través de ella y devuelve nulo, por lo que no considera adecuado para este propósito.
pero_hero
0

Dado que la indexación en ArrayList comienza desde 0 y termina un lugar antes del tamaño real, por lo tanto, la declaración correcta para devolver el último elemento de la lista sería:

int last = mylist.get (mylist.size () - 1);

Por ejemplo:

si el tamaño de la lista de la matriz es 5, entonces size-1 = 4 devolvería el último elemento de la matriz.

shravyaverma
fuente
-1

El último elemento de la lista es list.size() - 1. La colección está respaldada por una matriz y las matrices comienzan en el índice 0.

Entonces el elemento 1 en la lista está en el índice 0 en la matriz

El elemento 2 en la lista está en el índice 1 en la matriz

El elemento 3 en la lista está en el índice 2 en la matriz

y así..

MircoProgram
fuente
3
sin valor adicional a la respuesta anterior de @ JohannesSchaub
Karl Richter
-3

Qué tal esto ... En algún lugar de tu clase ...

List<E> list = new ArrayList<E>();
private int i = -1;
    public void addObjToList(E elt){
        i++;
        list.add(elt);
    }


    public E getObjFromList(){
        if(i == -1){ 
            //If list is empty handle the way you would like to... I am returning a null object
            return null; // or throw an exception
        }

        E object = list.get(i);
        list.remove(i); //Optional - makes list work like a stack
        i--;            //Optional - makes list work like a stack
        return object;
    }
rokrfellr
fuente
-3

Si modifica su lista, use listIterator()e itere desde el último índice (es decir, size()-1respectivamente). Si vuelve a fallar, verifique la estructura de su lista.

dae
fuente
-3

Todo lo que necesita hacer es usar size () para obtener el último valor de la Arraylist. Por ej. si tiene ArrayList de enteros, para obtener el último valor tendrá que

int lastValue = arrList.get(arrList.size()-1);

Recuerde, se puede acceder a los elementos en una Arraylist usando valores de índice. Por lo tanto, las ArrayLists se usan generalmente para buscar elementos.

usuario4660857
fuente
44
sin valor adicional a la respuesta anterior de @ JohannesSchaub
Karl Richter
-4

Las matrices almacenan su tamaño en una variable local llamada 'longitud'. Dada una matriz llamada "a", podría usar lo siguiente para hacer referencia al último índice sin conocer el valor del índice

a [a.length-1]

para asignar un valor de 5 a este último índice que usaría:

a [a.length-1] = 5;

closeab
fuente
Esta ArrayListno es una matriz.
glee8e
-6

Alternativa usando la API Stream:

list.stream().reduce((first, second) -> second)

Resultados en un Opcional del último elemento.

Terran
fuente
-7

En Kotlin, puedes usar el método last:

val lastItem = list.last()
Ollie
fuente
10
Sin embargo, esto es Java
Jachdich el
44
Una de las ideas detrás de la creación de Kotlin era cubrir los pequeños lados incómodos de Java. Así que creo que tiene sentido recomendar considerar Kotlin, al menos para las partes de la aplicación que realizan análisis de datos.
Eerik Sven Puudista