Come ottenere l'ultimo valore di una ArrayList


597

Come posso ottenere l'ultimo valore di una ArrayList?

Non conosco l'ultimo indice di ArrayList.


164
Ho votato a favore di questa domanda, perché mi chiedevo perché non esistesse un metodo del genere: getLastItem () e sono venuto a vedere se c'era una risposta. list.size () - 1 non è carino.
Nuno Gonçalves,

2
@ NunoGonçalves Puoi sempre subclassarlo!
Tim

12
Puoi sempre usare un LinkedList che ha il metodogetLast()
ssedano,

6
Elenco collegato che aggiunge un mucchio di spese generali. Usa Guava come mostrato di seguito: lastElement = Iterables.getLast (iterableList); O semplicemente indicizza una chiamata get () con size () - 1. Non è poi così brutto rispetto all'utilizzo di un elenco collegato quando non è richiesto. Si applicano soliti avvertimenti per quanto riguarda le condizioni di eccezione: consultare ArrayList javadoc.
RichieHH,

10
Usare list.size () -1 non è carino, ma usare un'API di terze parti solo per questo è peggio
Javo

Risposte:


692

Quanto segue fa parte Listdell'interfaccia (che ArrayList implementa):

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

Eè il tipo di elemento. Se l'elenco è vuoto, getgenera un IndexOutOfBoundsException. Puoi trovare l'intera documentazione API qui .


5
Questo causerà un'iterazione dell'elenco? Non mi sembra molto efficiente. Vengo dal C ++, dove ci sono effettivi metodi front () e back () sull'oggetto list, che sono implementati internamente con riferimenti head e tail. Esiste un meccanismo simile in Java?
Brady,

26
Non funzionerà cosa succede se l'elenco è vuoto, list.size () restituirà 0. e finirai con list.get (-1);
FRR

18
@feresr huh. Vuole ottenere l'ultimo valore nell'elenco. Ovviamente ciò implica che size () è> 0. Ciò sarebbe vero per qualsiasi tipo di implementazione. Leggere fino alla fine avrebbe risparmiato il tempo necessario per scrivere il tuo commento e il mio tempo per rispondere :) La mia risposta dice alla fine "Se l'elenco è vuoto, ottieni un IndexOutOfBoundsException"
Johannes Schaub - litb

16
@Brady non causerà un'iterazione O (n) per un ArrayList, perché come puoi immaginare, è supportato da un array. Quindi un semplice get (<index>) si traduce in un recupero a tempo costante da un array. (La fonte JDK lo conferma) Per altre implementazioni di elenchi, questo non è garantito, quindi per esempio LinkedList ha un metodo getLast () che è a tempo costante.
Peter,

9
Non riesco a capire perché abbiano deciso di implementare un lastElement()metodo semplice per loro Vectorma non per ArrayList. Che succede con quell'incongruenza?
Stefan Dimitrov,

211

Non esiste un modo elegante in vaniglia Java.

Google Guava

La libreria di Google Guava è fantastica: dai un'occhiata alla loro Iterablesclasse . Questo metodo genererà un NoSuchElementExceptionse l'elenco è vuoto, al contrario di un IndexOutOfBoundsException, come con l' size()-1approccio tipico - trovo NoSuchElementExceptionmolto più bello, o la possibilità di specificare un valore predefinito:

lastElement = Iterables.getLast(iterableList);

Puoi anche fornire un valore predefinito se l'elenco è vuoto, anziché un'eccezione:

lastElement = Iterables.getLast(iterableList, null);

oppure, se stai usando Opzioni:

lastElementRaw = Iterables.getLast(iterableList, null);
lastElement = (lastElementRaw == null) ? Option.none() : Option.some(lastElementRaw);

3
Sai se questo metodo fa una passeggiata lineare nell'elenco per trovare l'ultimo elemento?
BillMan,

5
@BillMan Nel caso di HashSet sì, nel caso di ArrayList no.
Simon,

6
Dovresti aggiungere che Iterables.getLastcontrolla se RandomAccessè implementato e quindi se accede alla voce in O (1).
Karl Richter,

1
Invece di Option, puoi usare Java nativo Optional. Sarà anche un po 'più pulito: lastElement = Optional.ofNullable(lastElementRaw);.
Little Helper,

186

questo dovrebbe farlo:

if (arrayList != null && !arrayList.isEmpty()) {
  T item = arrayList.get(arrayList.size()-1);
}

29
non c'è un modo elegante per farlo? : /
kommradHomer il

6
Probabilmente dovresti almeno dimostrare di assegnarlo ... ArrayList.get è privo di effetti collaterali.
Antony Stubbs,

È troppo meschino per indicare che quanto sopra non assegna / restituisce nulla?
Brian Agnew,

Se un ArrayList ha un solo record, si è verificata un'eccezione. Quale sarà la soluzione?
hasnain_ahmad,

2
@hasnain_ahmad, quando ArraList ha 1 elemento che funziona correttamente, dovresti preoccuparti di ArrayList e ArrayList non inizializzati con record zero. E questa risposta gestisce entrambi i casi
Farid,

27

Uso la classe micro-util per ottenere l'ultimo (e primo) elemento dell'elenco:

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

Leggermente più flessibile:

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

8
Usa solo guava. Non reinventare
fai clic su Aggiorna

15
@ClickUpvote L'utilizzo di Guava per un solo metodo minuscolo è in molti casi eccessivo. La mia risposta è per le persone che cercano una soluzione Java alla vaniglia . Se stai già utilizzando Guava nel tuo progetto, vedi altre risposte per la soluzione basata su Guava.
user11153

5
Se non usi la guava, finisci per scrivere molte classi di utilità come questa.
Fai clic su Aggiorna

6
A volte ottenere l'autorizzazione per aggiungere una libreria di terze parti può essere molto più complicato dell'aggiunta di una singola classe Java nativa. Ad esempio, i contratti governativi in ​​cui limitano e controllano le librerie di terze parti.
Dave Jarvis,

2
isEmptynon controlla se l'elenco è vuoto e quindi dovrebbe essere isNullOrEmptye non fa parte della domanda - o provi a migliorare l'insieme di risposte o fornisci classi di utilità (che sono una reinvenzione).
Karl Richter,

10

Il size()metodo restituisce il numero di elementi in ArrayList. I valori dell'indice degli elementi sono 0passati (size()-1), quindi dovresti usare myArrayList.get(myArrayList.size()-1)per recuperare l'ultimo elemento.



6

Non esiste un modo elegante per ottenere l'ultimo elemento di un elenco in Java (rispetto ad esempio items[-1]in Python).

Devi usare list.get(list.size()-1).

Quando si lavora con elenchi ottenuti da chiamate di metodo complicate, la soluzione alternativa risiede nella variabile temporanea:

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

Questa è l'unica opzione per evitare la versione brutta e spesso costosa o addirittura non funzionante:

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

Sarebbe bello se la correzione di questo difetto di progettazione fosse introdotta nell'API Java.


Non vedo qui un "difetto di progettazione", ciò che si evoca è un caso d'uso raro che non vale la pena aggiungere Listall'interfaccia. Perché dovresti chiamare un metodo per restituire un elenco, se sei interessato solo all'ultimo elemento? Non ricordo di averlo mai visto prima.
Dorian Gray,

1
@DorianGray La lettura dell'ultimo elemento da un elenco è un'operazione abbastanza comune ed list.get(list.size()-1)è l'esempio minimo che mostra il problema. Concordo sul fatto che gli esempi "avanzati" possano essere controversi e possibilmente un caso limite, volevo solo mostrare come il problema possa propagarsi ulteriormente. Supponiamo che la classe di someObjectsia straniera, proveniente da una biblioteca esterna.
Tregoreg,

Non vedo dove sia abbastanza comune, e se lo è, è meglio usarlo ArrayDequeinvece.
Dorian Gray,

@DorianGray Questa domanda ha molti voti e opinioni, quindi ci sono molte persone interessate a ottenere l'ultimo valore di un ArrayList.
Tregoreg,

5

Se puoi, scambia il ArrayListcon un ArrayDeque, che ha metodi convenienti come removeLast.


1
Ciò significa almeno un costo lineare rispetto al costo costante per l'accesso diretto, ma vale la pena menzionarlo.
Karl Richter,

@KarlRichter Sì. Ciò corrisponde all'assenza di metodi come get (int) nell'interfaccia di ArrayDeque. Questo è ciò che intendevo suggerire con "Se puoi"; se l'elenco non è accessibile per indice, forse non è necessario che sia un elenco.
John Glassmyer,

3

Come indicato nella soluzione, se Listè vuoto, IndexOutOfBoundsExceptionviene lanciato un. Una soluzione migliore è utilizzare il 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));
    }
}

Come prevedibile, l'ultimo elemento dell'elenco viene restituito come Optional:

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

Si occupa anche con grazia di elenchi vuoti:

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

2

Se invece usi una LinkedList, puoi accedere al primo elemento e all'ultimo con solo getFirst()e getLast()(se vuoi un modo più pulito di size () -1 e get (0))

Implementazione

Dichiara un LinkedList

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

Quindi questi sono i metodi che puoi usare per ottenere quello che vuoi, in questo caso stiamo parlando dell'elemento FIRST e LAST di un elenco

/**
     * 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);
    }

Quindi, allora puoi usare

mLinkedList.getLast(); 

per ottenere l'ultimo elemento dell'elenco.


1

guava fornisce un altro modo per ottenere l'ultimo elemento da un List:

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

se l'elenco fornito è vuoto, genera un IndexOutOfBoundsException


1
java.util.Collections#reverselo fa anche.
RoBeaToZ il

1
@RoBeaToZ, lo fa ma cambia l'elenco originale ripetendolo e restituisce vuoto, quindi non ritiene adatto a questo scopo.
pero_hero,

0

Poiché l'indicizzazione in ArrayList inizia da 0 e termina di una posizione prima della dimensione effettiva, quindi l'istruzione corretta per restituire l'ultimo elemento dell'arraylist sarebbe:

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

Per esempio:

se la dimensione dell'elenco di array è 5, allora size-1 = 4 restituirà l'ultimo elemento dell'array.


-1

L'ultimo elemento nell'elenco è list.size() - 1. La raccolta è supportata da una matrice e le matrici iniziano dall'indice 0.

Quindi l'elemento 1 nell'elenco è all'indice 0 dell'array

L'elemento 2 nell'elenco è nell'indice 1 dell'array

L'elemento 3 nell'elenco è nell'indice 2 dell'array

e così via..


3
nessun valore aggiuntivo alla precedente risposta di @ JohannesSchaub
Karl Richter,

-3

Che ne dici di questo ... Da qualche parte nella tua classe ...

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

-3

Se modifichi la tua lista, usa listIterator()e itera dall'ultimo indice (cioè size()-1rispettivamente). Se fallisci di nuovo, controlla la struttura della tua lista.


-3

Tutto quello che devi fare è usare size () per ottenere l'ultimo valore dell'Arraylist. Per es. se sei ArrayList di numeri interi, allora per ottenere l'ultimo valore dovrai

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

Ricorda, è possibile accedere agli elementi di un Arraylist usando i valori dell'indice. Pertanto, gli array sono generalmente utilizzati per cercare elementi.


4
nessun valore aggiuntivo alla precedente risposta di @ JohannesSchaub
Karl Richter,

-4

le matrici memorizzano le loro dimensioni in una variabile locale chiamata 'lunghezza'. Dato un array chiamato "a", è possibile utilizzare quanto segue per fare riferimento all'ultimo indice senza conoscere il valore dell'indice

un [a.length-1]

per assegnare un valore di 5 a questo ultimo indice dovresti usare:

un [a.length-1] = 5;


Questo ArrayListnon è un array.
glee8e

-6

Alternativa usando l'API Stream:

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

Risultati in un facoltativo dell'ultimo elemento.


-7

In Kotlin, puoi usare il metodo last:

val lastItem = list.last()

10
Questo è java comunque
Jachdich,

4
Una delle idee alla base della creazione di Kotlin era quella di coprire i piccoli lati scomodi di Java. Quindi penso che abbia senso raccomandare di considerare Kotlin, almeno per le parti dell'applicazione che eseguono l'analisi dei dati.
Eerik Sven Puudist,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.