Comment obtenir la dernière valeur d'une ArrayList

598

Comment obtenir la dernière valeur d'une ArrayList?

Je ne connais pas le dernier index de la ArrayList.

Jessy
la source
164
J'ai voté pour cette question, parce que je me demandais pourquoi il n'y avait pas une telle méthode comme: getLastItem () et je suis venu voir s'il y avait une réponse. list.size () - 1 n'est pas joli.
Nuno Gonçalves
2
@ NunoGonçalves Vous pouvez toujours le sous-classer!
Tim
12
Vous pouvez toujours utiliser une LinkedList qui a la méthodegetLast()
ssedano
6
Liste liée, elle ajoute un tas de frais généraux. Utilisez la goyave comme indiqué ci-dessous: lastElement = Iterables.getLast (iterableList); OU simplement indexer un appel get () avec size () - 1. Ce n'est pas si moche que d'utiliser une liste chaînée quand ce n'est pas nécessaire. Les mises en garde habituelles s'appliquent aux conditions d'exception - voir le javadoc ArrayList.
RichieHH
10
Utiliser list.size () -1 n'est pas joli, mais utiliser une API tierce juste pour cela est pire
Javo

Réponses:

693

Ce qui suit fait partie de l' Listinterface (qu'ArrayList implémente):

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

Eest le type d'élément. Si la liste est vide, getlance un IndexOutOfBoundsException. Vous pouvez trouver toute la documentation de l'API ici .

Johannes Schaub - litb
la source
5
Cela provoquera-t-il une itération de la liste? Cela ne me semble pas très efficace. Je viens de C ++, où il existe de réelles méthodes front () et back () sur l'objet liste, qui sont implémentées en interne avec des références head et tail. Existe-t-il un mécanisme similaire en Java?
Brady
26
Ne fonctionnera pas. que faire si la liste est vide, list.size () retournera 0. et vous vous retrouverez avec list.get (-1);
FRR
18
@feresr hein. Il veut obtenir la dernière valeur de la liste. Bien sûr, cela implique que size () est> 0. Ce serait vrai pour tout type d'implémentation. La lecture jusqu'à la fin aurait sauvé le temps dont vous aviez besoin pour écrire votre commentaire et mon temps pour répondre :) Ma réponse dit à la fin "Si la liste est vide, obtenez lève une IndexOutOfBoundsException"
Johannes Schaub - litb
16
@Brady, il ne provoquera pas d'itération O (n) pour une ArrayList, car comme vous pouvez le deviner, il est soutenu par un tableau. Ainsi, un simple get (<index>) se traduit simplement par une récupération à temps constant à partir d'un tableau. (La source JDK le confirme) Pour les autres implémentations de liste, cela n'est pas garanti, donc par exemple, LinkedList a une méthode getLast () qui est à temps constant.
Peter
9
Je ne comprends pas pourquoi ils ont décidé de mettre en œuvre une lastElement()méthode simple pour leur Vectormais pas pour ArrayList. Qu'est-ce qui se passe avec cette incohérence?
Stefan Dimitrov
211

Il n'y a pas de méthode élégante en Java vanille.

Google Guava

La bibliothèque Google Guava est géniale - consultez leur Iterablesclasse . Cette méthode lancera un NoSuchElementExceptionsi la liste est vide, par opposition à un IndexOutOfBoundsException, comme avec l' size()-1approche typique - je trouve NoSuchElementExceptionbeaucoup plus agréable, ou la possibilité de spécifier un défaut:

lastElement = Iterables.getLast(iterableList);

Vous pouvez également fournir une valeur par défaut si la liste est vide, au lieu d'une exception:

lastElement = Iterables.getLast(iterableList, null);

ou, si vous utilisez les options:

lastElementRaw = Iterables.getLast(iterableList, null);
lastElement = (lastElementRaw == null) ? Option.none() : Option.some(lastElementRaw);
Antony Stubbs
la source
3
Savez-vous si cette méthode fait une marche linéaire dans la liste pour trouver le dernier élément?
BillMan
5
@BillMan Dans le cas de HashSet oui, dans le cas de ArrayList non.
Simon
6
Vous devez ajouter cette Iterables.getLastvérification si elle RandomAccessest implémentée et donc si elle accède à l'élément dans O (1).
Karl Richter
1
Au lieu de Option, vous pouvez utiliser le Java natif Optional. Il sera également un peu plus propre: lastElement = Optional.ofNullable(lastElementRaw);.
Little Helper
186

cela devrait le faire:

if (arrayList != null && !arrayList.isEmpty()) {
  T item = arrayList.get(arrayList.size()-1);
}
Henrik Paul
la source
29
n'y a-t-il pas de façon élégante de le faire? : /
kommradHomer
6
Vous devriez probablement au moins démontrer l'attribution ... ArrayList.get est sans effets secondaires.
Antony Stubbs
Est-il trop mesquin pour indiquer que ce qui précède n'affecte / ne renvoie rien?
Brian Agnew
Si une ArrayList n'a qu'un seul enregistrement, une exception s'est produite. Quelle sera la solution?
hasnain_ahmad
2
@hasnain_ahmad, lorsque ArraList a 1 élément, cela fonctionne correctement, vous devriez vous soucier des ArrayList et ArrayList non initialisés avec zéro enregistrement. Et cette réponse traite les deux cas
Farid
27

J'utilise la classe micro-util pour obtenir le dernier (et le premier) élément de la liste:

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

Un peu plus 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();
  }
}
user11153
la source
8
Utilisez simplement la goyave. Ne réinventez pas
Cliquez sur Upvote
15
@ClickUpvote L'utilisation de la goyave pour une seule méthode minuscule est dans de nombreux cas une exagération. Ma réponse est pour les personnes à la recherche d'une solution Java vanille . Si vous utilisez déjà la goyave dans votre projet, consultez une autre réponse pour une solution basée sur la goyave.
user11153
5
Si vous n'utilisez pas la goyave, vous finissez par écrire de nombreuses classes d'utilitaires comme celle-ci.
Cliquez sur Upvote
6
Parfois, obtenir l'autorisation d'ajouter une bibliothèque tierce peut être beaucoup plus complexe que l'ajout d'une seule classe Java native. Par exemple, les contrats gouvernementaux où ils limitent et filtrent les bibliothèques tierces.
Dave Jarvis
2
isEmptyne vérifie pas si la liste est vide et devrait donc l'être isNullOrEmptyet cela ne fait pas partie de la question - soit vous essayez d'améliorer l'ensemble des réponses, soit vous fournissez des classes d'utilité (qui sont une réinvention).
Karl Richter
10

La size()méthode renvoie le nombre d'éléments dans ArrayList. Les valeurs d'index des éléments sont 0terminées (size()-1), vous pouvez donc utiliser myArrayList.get(myArrayList.size()-1)pour récupérer le dernier élément.

Ken Paul
la source
6

Utilisation de lambdas:

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

Il n'y a aucun moyen élégant d'obtenir le dernier élément d'une liste en Java (par exemple items[-1]en Python).

Vous devez utiliser list.get(list.size()-1).

Lorsque vous travaillez avec des listes obtenues par des appels de méthode compliqués, la solution réside dans la variable temporaire:

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

C'est la seule option pour éviter une version moche et souvent chère voire ne fonctionnant pas:

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

Ce serait bien si un correctif pour cette faille de conception était introduit dans l'API Java.

Tregoreg
la source
Je ne vois pas de "défaut de conception" ici, ce que vous évoquez est un cas d'utilisation rare qui ne vaut pas la peine d'être ajouté à l' Listinterface. Pourquoi voudriez-vous appeler une méthode renvoyant une liste, si vous n'êtes intéressé que par le dernier élément? Je ne me souviens pas avoir vu cela auparavant.
Dorian Gray
1
@DorianGray La lecture du dernier élément d'une liste est une opération assez courante et list.get(list.size()-1)est l'exemple minimal montrant le problème. Je suis d'accord que les exemples "avancés" peuvent être controversés et peut-être un cas limite, je voulais juste montrer comment le problème peut se propager davantage. Supposons que la classe de someObjectsoit étrangère, provenant d'une bibliothèque externe.
Tregoreg
Je ne vois pas où c'est assez courant, et si c'est le cas, vous feriez mieux de l'utiliser à la ArrayDequeplace.
Dorian Gray
@DorianGray Cette question a beaucoup de votes positifs et d'opinions, donc il y a beaucoup de gens intéressés à obtenir la dernière valeur d'un ArrayList.
Tregoreg
5

Si vous le pouvez, remplacez le ArrayListpar un ArrayDeque, qui a des méthodes pratiques comme removeLast.

John Glassmyer
la source
1
Cela signifie au moins un coût linéaire par rapport au coût constant pour un accès direct, mais mérite d'être mentionné.
Karl Richter
@KarlRichter Oui. Cela correspond à l'absence de méthodes comme get (int) dans l'interface d'ArrayDeque. C'est ce que je voulais dire par "si vous le pouvez"; si la liste n'est pas accessible par index, il n'est peut-être pas nécessaire que ce soit une liste.
John Glassmyer
3

Comme indiqué dans la solution, si le Listest vide, un IndexOutOfBoundsExceptionest lancé. Une meilleure solution consiste à utiliser le Optionaltype:

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

Comme vous vous en doutez, le dernier élément de la liste est renvoyé sous la forme Optional:

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

Il traite également gracieusement les listes vides:

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

Si vous utilisez une LinkedList à la place, vous pouvez accéder au premier élément et au dernier avec juste getFirst()et getLast()(si vous voulez un moyen plus propre que size () -1 et obtenez (0))

la mise en oeuvre

Déclarez une LinkedList

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

Ensuite , ce sont les méthodes que vous pouvez utiliser pour obtenir ce que vous voulez, dans ce cas , nous parlons de FIRST et LAST élément d'une 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);
    }

Vous pouvez donc utiliser

mLinkedList.getLast(); 

pour obtenir le dernier élément de la liste.

Gastón Saillén
la source
1

la goyave fournit un autre moyen d'obtenir le dernier élément d'un List:

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

si la liste fournie est vide, elle lance un IndexOutOfBoundsException

pero_hero
la source
1
java.util.Collections#reversele fait aussi.
RoBeaToZ
1
@RoBeaToZ, il le fait, mais il modifie la liste d'origine en itérant à travers elle et retourne vide, donc il ne juge pas approprié à cette fin.
pero_hero
0

Étant donné que l'indexation dans ArrayList commence à 0 et se termine à une place avant la taille réelle, la déclaration correcte pour renvoyer le dernier élément arraylist serait:

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

Par exemple:

si la taille de la liste de tableaux est 5, alors size-1 = 4 retournerait le dernier élément du tableau.

shravyaverma
la source
-1

Le dernier élément de la liste est list.size() - 1. La collection est soutenue par un tableau et les tableaux commencent à l'index 0.

L'élément 1 de la liste est donc à l'index 0 du tableau

L'élément 2 de la liste est à l'index 1 du tableau

L'élément 3 de la liste est à l'index 2 du tableau

etc..

MircoProgram
la source
3
aucune valeur supplémentaire à la réponse précédente de @ JohannesSchaub
Karl Richter
-3

Que diriez-vous de cela ... Quelque part dans votre 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;
    }
rokrfellr
la source
-3

Si vous modifiez votre liste, utilisez listIterator()et répétez le dernier index (c'est-à-dire size()-1respectivement). Si vous échouez à nouveau, vérifiez la structure de votre liste.

dae
la source
-3

Tout ce que vous devez faire est d'utiliser size () pour obtenir la dernière valeur de l'arraylist. Par exemple. si vous ArrayList d'entiers, alors pour obtenir la dernière valeur, vous devrez

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

N'oubliez pas que les éléments d'une liste Arraylist sont accessibles à l'aide de valeurs d'index. Par conséquent, les listes de tableaux sont généralement utilisées pour rechercher des éléments.

user4660857
la source
4
aucune valeur supplémentaire à la réponse précédente de @ JohannesSchaub
Karl Richter
-4

les tableaux stockent leur taille dans une variable locale appelée «longueur». Étant donné un tableau nommé "a", vous pouvez utiliser ce qui suit pour référencer le dernier index sans connaître la valeur d'index

a [a.length-1]

pour attribuer une valeur de 5 à ce dernier index, vous utiliseriez:

a [a.length-1] = 5;

fermer
la source
Ce n'est ArrayListpas un tableau.
glee8e
-6

Alternative utilisant l'API Stream:

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

Entraîne une option du dernier élément.

Terran
la source
-7

Dans Kotlin, vous pouvez utiliser la méthode last:

val lastItem = list.last()
Ollie
la source
10
C'est Java cependant
Jachdich
4
L'une des idées derrière la création de Kotlin était de couvrir les petits côtés inconfortables de Java. Je pense donc qu'il est logique de recommander d'envisager Kotlin, au moins pour les parties de l'application qui effectuent des analyses de données.
Eerik Sven Puudist