So erhalten Sie den letzten Wert einer ArrayList

597

Wie kann ich den letzten Wert einer ArrayList erhalten?

Ich kenne den letzten Index der ArrayList nicht.

Jessy
quelle
164
Ich habe diese Frage positiv bewertet, weil ich mich gefragt habe, warum es keine solche Methode wie getLastItem () gibt, und bin gekommen, um zu sehen, ob es eine Antwort gibt. list.size () - 1 ist nicht schön.
Nuno Gonçalves
2
@ NunoGonçalves Du kannst es immer unterordnen!
Tim
12
Sie können immer eine LinkedList verwenden, die die MethodegetLast()
ssedano
6
Die verknüpfte Auflistung fügt einen ganzen Haufen Overhead hinzu. Verwenden Sie Guava wie unten gezeigt: lastElement = Iterables.getLast (iterableList); ODER indizieren Sie einfach einen get () -Aufruf mit size () - 1. Es ist nicht so hässlich im Vergleich zur Verwendung einer verknüpften Liste, wenn dies nicht erforderlich ist. In Bezug auf Ausnahmebedingungen gelten die üblichen Einschränkungen - siehe ArrayList-Javadoc.
RichieHH
10
Die Verwendung von list.size () -1 ist nicht schön, aber die Verwendung einer Drittanbieter-API nur dafür ist schlimmer
Javo

Antworten:

692

Folgendes ist Teil der ListSchnittstelle (die ArrayList implementiert):

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

Eist der Elementtyp. Wenn die Liste leer ist, wird ein getausgelöst IndexOutOfBoundsException. Die gesamte API-Dokumentation finden Sie hier .

Johannes Schaub - litb
quelle
5
Wird dies zu einer Iteration der Liste führen? Das scheint mir nicht sehr effizient zu sein. Ich komme aus C ++, wo es tatsächliche front () - und back () -Methoden für das Listenobjekt gibt, die intern mit Head- und Tail-Referenzen implementiert sind. Gibt es einen ähnlichen Mechanismus in Java?
Brady
26
Wird nicht funktionieren. Was passiert, wenn die Liste leer ist? List.size () gibt 0 zurück und Sie erhalten list.get (-1).
FRR
18
@feresr huh. Er möchte den letzten Wert in der Liste erhalten. Das bedeutet natürlich, dass size ()> 0 ist. Das würde für jede Art von Implementierung gelten. Das Durchlesen bis zum Ende hätte die Zeit gespart, die Sie zum Schreiben Ihres Kommentars und meiner Zeit für die Beantwortung benötigt haben :) Meine Antwort lautet am Ende "Wenn die Liste leer ist, wird eine IndexOutOfBoundsException ausgelöst"
Johannes Schaub - litb
16
@Brady verursacht keine O (n) -Iteration für eine ArrayList, da sie, wie Sie sich vorstellen können, von einem Array unterstützt wird. Ein einfaches Abrufen (<Index>) führt also nur zu einem zeitkonstanten Abruf aus einem Array. (JDK-Quelle bestätigt dies) Für andere Listenimplementierungen ist dies nicht garantiert. Daher verfügt LinkedList beispielsweise über eine zeitkonstante Methode getLast ().
Peter
9
Ich kann nicht verstehen, warum sie beschlossen haben, eine einfache lastElement()Methode für sie zu implementieren, Vectoraber nicht für ArrayList. Was ist mit dieser Inkonsistenz los?
Stefan Dimitrov
211

In Vanille-Java gibt es keinen eleganten Weg.

Google Guava

Die Google Guava- Bibliothek ist großartig - sehen Sie sich ihre IterablesKlasse an . Diese Methode löst a aus, NoSuchElementExceptionwenn die Liste leer ist, im Gegensatz zu a IndexOutOfBoundsException, wie beim typischen size()-1Ansatz - ich finde einen NoSuchElementExceptionviel schöneren oder die Möglichkeit, einen Standard anzugeben:

lastElement = Iterables.getLast(iterableList);

Sie können anstelle einer Ausnahme auch einen Standardwert angeben, wenn die Liste leer ist:

lastElement = Iterables.getLast(iterableList, null);

oder, wenn Sie Optionen verwenden:

lastElementRaw = Iterables.getLast(iterableList, null);
lastElement = (lastElementRaw == null) ? Option.none() : Option.some(lastElementRaw);
Antony Stubbs
quelle
3
Wissen Sie, ob diese Methode einen linearen Spaziergang durch die Liste macht, um das letzte Element zu finden?
BillMan
5
@ BillMan Im Fall von HashSet ja, im Fall von ArrayList nein.
Simon
6
Sie sollten diese Iterables.getLastPrüfung hinzufügen, ob sie RandomAccessimplementiert ist und daher auf das Element in O (1) zugreift.
Karl Richter
1
Stattdessen Optionkönnen Sie das native Java verwenden Optional. Es wird auch etwas sauberer : lastElement = Optional.ofNullable(lastElementRaw);.
Kleiner Helfer
186

das sollte es tun:

if (arrayList != null && !arrayList.isEmpty()) {
  T item = arrayList.get(arrayList.size()-1);
}
Henrik Paul
quelle
29
Gibt es keinen schlanken Weg, dies zu tun? : /
kommradHomer
6
Sie sollten wahrscheinlich zumindest die Zuweisung demonstrieren ... ArrayList.get ist frei von Nebenwirkungen.
Antony Stubbs
Ist es zu kleinlich, um anzuzeigen, dass das oben Gesagte nichts zuweist / zurückgibt?
Brian Agnew
Wenn eine ArrayList nur einen Datensatz enthält, ist eine Ausnahme aufgetreten. Was wird die Lösung sein?
hasnain_ahmad
2
@hasnain_ahmad, wenn ArraList 1 Element hat, das ordnungsgemäß funktioniert, sollten Sie sich über nicht initialisierte ArrayList und ArrayList mit Null-Datensatz Gedanken machen. Und diese Antwort behandelt beide Fälle
Farid
27

Ich benutze die Micro-Util-Klasse, um das letzte (und erste) Element der Liste zu erhalten:

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

Etwas flexibler:

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();
  }
}
user11153
quelle
8
Verwenden Sie einfach Guave. Nicht neu erfinden
Klicken Sie auf Upvote
15
@ClickUpvote Die Verwendung von Guava für nur eine winzige Methode ist in vielen Fällen ein Overkill. Meine Antwort ist für Leute, die nach einer Vanille-Java-Lösung suchen . Wenn Sie Guava bereits in Ihrem Projekt verwenden, finden Sie eine andere Antwort für eine Guava-basierte Lösung.
user11153
5
Wenn Sie keine Guave verwenden, schreiben Sie am Ende viele Dienstprogrammklassen wie diese.
Klicken Sie auf Upvote
6
Manchmal ist es viel aufwendiger, die Berechtigung zum Hinzufügen einer Bibliothek eines Drittanbieters zu erhalten, als eine einzelne native Java-Klasse hinzuzufügen. Zum Beispiel Regierungsverträge, bei denen Bibliotheken von Drittanbietern eingeschränkt und überprüft werden.
Dave Jarvis
2
isEmptyprüft nicht, ob die Liste leer ist und daher leer sein sollte, isNullOrEmptyund das ist nicht Teil der Frage - entweder versuchen Sie, die Antworten zu verbessern, oder Sie stellen Dienstprogrammklassen zur Verfügung (die eine Neuerfindung darstellen).
Karl Richter
10

Die size()Methode gibt die Anzahl der Elemente in der ArrayList zurück. Die Indexwerte der Elemente sind 0durch (size()-1), sodass Sie myArrayList.get(myArrayList.size()-1)das letzte Element abrufen würden .

Ken Paul
quelle
6

Verwenden von Lambdas:

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

Es gibt keine elegante Möglichkeit, das letzte Element einer Liste in Java abzurufen (im Vergleich zu z items[-1]. B. in Python).

Du musst benutzen list.get(list.size()-1).

Bei der Arbeit mit Listen, die durch komplizierte Methodenaufrufe erhalten wurden, liegt die Problemumgehung in einer temporären Variablen:

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

Dies ist die einzige Option, um hässliche und oft teure oder gar nicht funktionierende Versionen zu vermeiden:

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

Es wäre schön, wenn die Korrektur für diesen Konstruktionsfehler in die Java-API eingeführt würde.

Tregoreg
quelle
Ich sehe hier keinen "Designfehler". Was Sie ansprechen, ist ein seltener Anwendungsfall, der es nicht wert ist, zur ListBenutzeroberfläche hinzugefügt zu werden. Warum sollten Sie eine Methode aufrufen, die eine Liste zurückgibt, wenn Sie nur am letzten Element interessiert sind? Ich erinnere mich nicht, dass ich das jemals zuvor gesehen habe.
Dorian Gray
1
@DorianGray Das Lesen des letzten Elements aus einer Liste ist eine ziemlich häufige Operation und list.get(list.size()-1)das minimale Beispiel, das das Problem zeigt. Ich stimme zu, dass die "fortgeschrittenen" Beispiele kontrovers und möglicherweise ein Randfall sein können. Ich wollte nur zeigen, wie sich das Problem weiter verbreiten kann. Nehmen wir an, dass die Klasse von someObjectfremd ist und aus einer externen Bibliothek stammt.
Tregoreg
Ich sehe nicht, wo dies ziemlich häufig ist, und wenn ja, verwenden Sie es ArrayDequestattdessen besser .
Dorian Gray
@DorianGray Diese Frage hat viele positive Stimmen und Ansichten, daher gibt es viele Leute, die daran interessiert sind, den letzten Wert von a zu erhalten ArrayList.
Tregoreg
5

Wenn Sie können, tauschen Sie die ArrayListgegen eine ArrayDeque, die bequeme Methoden wie hat removeLast.

John Glassmyer
quelle
1
Dies bedeutet zumindest lineare Kosten im Vergleich zu konstanten Kosten für den direkten Zugriff, ist jedoch erwähnenswert.
Karl Richter
@KarlRichter Ja. Dies entspricht dem Fehlen von Methoden wie get (int) in der ArrayDeque-Schnittstelle. Dies ist, was ich mit "Wenn du kannst" vorschlagen wollte; Wenn auf die Liste nicht über den Index zugegriffen wird, muss es sich möglicherweise nicht um eine Liste handeln.
John Glassmyer
3

Wie in der Lösung angegeben, Listwird ein IndexOutOfBoundsExceptiongeworfen , wenn das leer ist. Eine bessere Lösung ist die Verwendung des OptionalTyps:

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

Wie zu erwarten, wird das letzte Element der Liste als Optional: zurückgegeben.

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

Es geht auch elegant mit leeren Listen um:

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

Wenn Sie stattdessen eine LinkedList verwenden, können Sie mit just getFirst()und getLast()(wenn Sie einen saubereren Weg als size () -1 und get (0) möchten) auf das erste und das letzte Element zugreifen.

Implementierung

Deklarieren Sie eine LinkedList

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

Dann sind dies die Methoden, mit denen Sie das bekommen können, was Sie wollen. In diesem Fall handelt es sich um das ERSTE und LETZTE Element einer Liste

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

Also, dann kannst du verwenden

mLinkedList.getLast(); 

um das letzte Element der Liste zu erhalten.

Gastón Saillén
quelle
1

Guave bietet eine andere Möglichkeit, das letzte Element aus einem zu erhalten List:

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

Wenn die bereitgestellte Liste leer ist, wird ein IndexOutOfBoundsException

pero_hero
quelle
1
java.util.Collections#reversemacht es auch.
RoBeaToZ
1
@RoBeaToZ, es tut es, aber es ändert die ursprüngliche Liste, indem es sie durchläuft, und gibt void zurück, so dass es nicht für diesen Zweck geeignet erscheint.
pero_hero
0

Da die Indizierung in ArrayList bei 0 beginnt und eine Stelle vor der tatsächlichen Größe endet, lautet die korrekte Anweisung zur Rückgabe des letzten Arraylist-Elements:

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

Zum Beispiel:

Wenn die Größe der Array-Liste 5 beträgt, gibt size-1 = 4 das letzte Array-Element zurück.

shravyaverma
quelle
-1

Das letzte Element in der Liste ist list.size() - 1. Die Sammlung wird von einem Array unterstützt und Arrays beginnen bei Index 0.

Element 1 in der Liste befindet sich also am Index 0 im Array

Element 2 in der Liste befindet sich am Index 1 im Array

Element 3 in der Liste befindet sich am Index 2 im Array

und so weiter..

MircoProgramm
quelle
3
Kein zusätzlicher Wert zu @ JohannesSchaubs früherer Antwort
Karl Richter
-3

Wie wäre es damit .. Irgendwo in deiner Klasse ...

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
quelle
-3

Wenn Sie Ihre Liste ändern, verwenden Sie den listIterator()letzten Index (dh size()-1). Wenn Sie erneut fehlschlagen, überprüfen Sie Ihre Listenstruktur.

dae
quelle
-3

Sie müssen lediglich size () verwenden, um den letzten Wert der Arraylist zu erhalten. Zum Beispiel. Wenn Sie eine ArrayList von Ganzzahlen haben, müssen Sie den letzten Wert ermitteln

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

Denken Sie daran, dass auf Elemente in einer Arrayliste mithilfe von Indexwerten zugegriffen werden kann. Daher werden ArrayLists im Allgemeinen zum Suchen von Elementen verwendet.

user4660857
quelle
4
Kein zusätzlicher Wert zu @ JohannesSchaubs früherer Antwort
Karl Richter
-4

Arrays speichern ihre Größe in einer lokalen Variablen namens "Länge". Bei einem Array mit dem Namen "a" können Sie Folgendes verwenden, um auf den letzten Index zu verweisen, ohne den Indexwert zu kennen

a [a.Länge-1]

Um diesem letzten Index den Wert 5 zuzuweisen, würden Sie Folgendes verwenden:

a [a.Länge-1] = 5;

verschließbar
quelle
Dies ist ArrayListkein Array.
Glee8e
-6

Alternative mit der Stream-API:

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

Ergibt eine Option des letzten Elements.

Terraner
quelle
-7

In Kotlin können Sie die folgende Methode verwenden last:

val lastItem = list.last()
Ollie
quelle
10
Dies ist jedoch Java
Jachdich
4
Eine der Ideen bei der Erstellung von Kotlin war es, die kleinen unangenehmen Seiten von Java zu behandeln. Daher halte ich es für sinnvoll, Kotlin in Betracht zu ziehen, zumindest für die Teile der Anwendung, die Datenanalysen durchführen.
Eerik Sven Puudist