Como obter o último valor de um ArrayList

597

Como posso obter o último valor de um ArrayList?

Não conheço o último índice do ArrayList.

Jessy
fonte
164
Votei positivamente nesta pergunta, porque estava me perguntando por que não existe um método como esse: getLastItem () e vim ver se havia uma resposta. list.size () - 1 não é bonito.
Nuno Gonçalves
2
@ NunoGonçalves Você sempre pode subclassificar!
Tim
12
Você pode sempre usar um LinkedList que tem o métodogetLast()
ssedano
6
A listagem vinculada adiciona um monte de sobrecarga. Use o Goiaba, como mostrado abaixo: lastElement = Iterables.getLast (iterableList); OU simplesmente indexe uma chamada get () com tamanho () - 1. Não é tão feio comparado ao uso de uma lista vinculada quando não é necessário. Advertências comuns se aplicam a condições de exceção - consulte o javadoc ArrayList.
RichieHH
10
Usando list.size () -1 não é bonito, mas usando um terceiro partido API apenas para isso é pior
Javo

Respostas:

692

A seguir, parte da Listinterface (que o ArrayList implementa):

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

Eé o tipo de elemento Se a lista estiver vazia, getlança um IndexOutOfBoundsException. Você pode encontrar toda a documentação da API aqui .

Johannes Schaub - litb
fonte
5
Isso causará uma iteração da lista? Isso não parece muito eficiente para mim. Eu venho de C ++, onde existem métodos front () e back () reais no objeto list, que são implementados internamente com referências de cabeçalho e cauda. Existe um mecanismo semelhante em Java?
Brady13 /
26
Não vai funcionar. e se a lista estiver vazia, list.size () retornará 0. e você terminará com list.get (-1);
FRR 21/01
18
@feresr huh. Ele quer obter o último valor da lista. É claro que isso implica que size () é> 0. Isso seria verdade para qualquer tipo de implementação. Ler até o final economizaria o tempo necessário para escrever seu comentário e o tempo para responder :) Minha resposta diz no final "Se a lista estiver vazia, jogue uma IndexOutOfBoundsException"
Johannes Schaub - litb
16
@Brady não causará uma iteração O (n) para um ArrayList, porque, como você pode imaginar, ele é apoiado por um array. Portanto, um simples get (<índice>) resulta apenas em uma recuperação de tempo constante de uma matriz. (A fonte JDK confirma isso) Para outras implementações de lista, isso não é garantido; portanto, por exemplo, o LinkedList possui um método getLast () que é constante.
Peter Peter
9
Não consigo entender por que eles decidiram implementar um lastElement()método simples para eles, Vectormas não para eles ArrayList. O que há com essa inconsistência?
Stefan Dimitrov
211

Não há uma maneira elegante no Java de baunilha.

Google Guava

A biblioteca do Google Guava é ótima - confira a Iterablesaula deles . Este método lançará a NoSuchElementExceptionse a lista estiver vazia, em oposição a uma IndexOutOfBoundsException, como na size()-1abordagem típica - acho NoSuchElementExceptionmuito mais agradável ou a capacidade de especificar um padrão:

lastElement = Iterables.getLast(iterableList);

Você também pode fornecer um valor padrão se a lista estiver vazia, em vez de uma exceção:

lastElement = Iterables.getLast(iterableList, null);

ou, se você estiver usando Opções:

lastElementRaw = Iterables.getLast(iterableList, null);
lastElement = (lastElementRaw == null) ? Option.none() : Option.some(lastElementRaw);
Antony Stubbs
fonte
3
Você sabe se esse método faz uma caminhada linear pela lista para encontrar o último elemento?
Billman
5
@ BillMan No caso do HashSet, sim, no caso do ArrayList no.
19613 Simon
6
Você deve adicionar isso Iterables.getLast verificação se RandomAccessestá implementado e, portanto, se acessa o item em O (1).
Karl Richter
1
Em vez de Option, você pode usar o Java nativo Optional. Também será um pouco mais limpo:lastElement = Optional.ofNullable(lastElementRaw); .
Little Helper
186

Isso deve servir:

if (arrayList != null && !arrayList.isEmpty()) {
  T item = arrayList.get(arrayList.size()-1);
}
Henrik Paul
fonte
29
não existe uma maneira elegante de fazer isso? : /
kommradHomer 5/12
6
Provavelmente você deve pelo menos demonstrar a atribuição ... ArrayList.get é livre de efeitos colaterais.
Antony Stubbs
É muito mesquinho indicar que o item acima não atribui / retorna nada?
Brian Agnew
Se um ArrayList tiver apenas um registro, ocorrerá uma exceção. Qual será a solução?
hasnain_ahmad
2
@hasnain_ahmad, quando o ArraList tem um elemento que funciona corretamente, você deve se preocupar com ArrayList e ArrayList não inicializados com zero registro. E essa resposta lida com os dois casos
Farid
27

Eu uso a classe micro-util para obter o último (e primeiro) elemento da 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;
    }
}

Um pouco mais flexível:

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
fonte
8
Basta usar goiaba. Não reinvente
Click Upvote
15
@ClickUpvote Usar o Goiaba para apenas um método minúsculo é, em muitos casos, um exagero. Minha resposta é para pessoas que procuram solução Java baunilha . Se você já estiver usando o Guava em seu projeto, consulte outra resposta para a solução baseada em Guava.
precisa saber é o seguinte
5
Se você não usa goiaba, acaba escrevendo muitas classes de utilitários como esta.
Click UpVote
6
Às vezes, obter permissão para adicionar uma biblioteca de terceiros pode ser muito mais envolvente do que adicionar uma única classe Java nativa. Por exemplo, contratos governamentais onde eles limitam e examinam bibliotecas de terceiros.
Dave Jarvis
2
isEmptynão verifica se a lista está vazia e, portanto, deve estar isNullOrEmptye isso não faz parte da pergunta - você tenta aprimorar o conjunto de respostas ou fornece classes de utilidade (que são uma reinvenção).
Karl Richter
10

O size()método retorna o número de elementos no ArrayList. Os valores de índice dos elementos são 0cumpridos (size()-1), portanto, você usaria myArrayList.get(myArrayList.size()-1)para recuperar o último elemento.

Ken Paul
fonte
6

Usando lambdas:

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

Não existe uma maneira elegante de obter o último elemento de uma lista em Java (comparado com, por exemplo, items[-1]em Python).

Você tem que usar list.get(list.size()-1).

Ao trabalhar com listas obtidas por chamadas de método complicadas, a solução alternativa está na variável temporária:

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

Esta é a única opção para evitar a versão feia e muitas vezes cara ou mesmo não funcional:

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

Seria bom se a correção para essa falha de design fosse introduzida na API Java.

Tregoreg
fonte
Não vejo uma "falha de design" aqui, o que você menciona é um caso de uso raro que não vale a pena ser adicionado à Listinterface. Por que você deseja chamar um método retornando uma lista, se você está interessado apenas no último elemento? Não me lembro de ter visto isso antes.
Dorian Gray
1
@DorianGray Ler o último elemento de uma lista é uma operação bastante comum e list.get(list.size()-1)é o exemplo mínimo que mostra o problema. Concordo que os exemplos "avançados" podem ser controversos e, possivelmente, um caso crítico, eu só queria mostrar como o problema pode se propagar ainda mais. Vamos supor que a classe de someObjecté estrangeira, proveniente de biblioteca externa.
Tregoreg
Não vejo onde isso é bastante comum e, se for, é melhor você usar ArrayDeque.
Dorian Gray
@DorianGray Esta questão tem muitos votos positivos e pontos de vista, por isso há muitas pessoas interessadas em obter o último valor de um ArrayList.
Tregoreg
5

Se você puder, troque por ArrayListfor ArrayDeque, que possui métodos convenientes, como removeLast.

John Glassmyer
fonte
1
Isso significa pelo menos custo linear em comparação com custo constante de acesso direto, mas vale a pena mencionar.
Karl Richter
@KarlRichter Sim. Isso corresponde à ausência de métodos como get (int) na interface do ArrayDeque. Isto é o que eu quis sugerir com "Se você puder"; se a lista não estiver sendo acessada pelo índice, talvez não seja uma lista.
9119 John Glassmyer
3

Conforme indicado na solução, se o Listestiver vazio, um IndexOutOfBoundsExceptioné lançado. Uma solução melhor é usar o 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 seria de esperar, o último elemento da lista é retornado como Optional:

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

Ele também lida com listas vazias também:

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

Se você usar um LinkedList, poderá acessar o primeiro elemento e o último com just getFirst()e getLast()(se desejar uma maneira mais limpa que size () -1 e get (0))

Implementação

Declarar uma LinkedList

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

Então, esses são os métodos que você pode usar para obter o que deseja. Nesse caso, estamos falando sobre o PRIMEIRO e O ÚLTIMO elemento de uma 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);
    }

Então você pode usar

mLinkedList.getLast(); 

para obter o último elemento da lista.

Gastón Saillén
fonte
1

goiaba fornece outra maneira de obter o último elemento de um List:

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

se a lista fornecida estiver vazia, lança uma IndexOutOfBoundsException

pero_hero
fonte
1
java.util.Collections#reversefaz isso também.
RoBeaToZ
1
@RoBeaToZ, ele muda, mas altera a lista original, iterando através dela e retorna nulo, para que não considere adequado a esse propósito.
pero_hero 22/04
0

Como a indexação em ArrayList começa em 0 e termina em um lugar antes do tamanho real, a instrução correta para retornar o último elemento de arraylist seria:

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

Por exemplo:

se o tamanho da lista de matrizes for 5, size-1 = 4 retornará o último elemento da matriz.

shravyaverma
fonte
-1

O último item da lista é list.size() - 1 . A coleção é apoiada por uma matriz e as matrizes começam no índice 0.

Portanto, o elemento 1 da lista está no índice 0 da matriz

O elemento 2 da lista está no índice 1 na matriz

O elemento 3 da lista está no índice 2 da matriz

e assim por diante..

MircoProgram
fonte
3
valor nenhum adicional para @ resposta anterior da JohannesSchaub
Karl Richter
-3

Que tal isso ... Em algum lugar da sua 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
fonte
-3

Se você modificar sua lista, use listIterator()e repita a partir do último índice (que é size()-1respectivamente). Se você falhar novamente, verifique a estrutura da sua lista.

dae
fonte
-3

Tudo que você precisa fazer é usar size () para obter o último valor da lista de matrizes. Por ex. se você ArrayList de números inteiros, para obter o último valor, você terá que

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

Lembre-se, os elementos em uma lista de matriz podem ser acessados ​​usando valores de índice. Portanto, ArrayLists geralmente são usadas para pesquisar itens.

user4660857
fonte
4
valor nenhum adicional para @ resposta anterior da JohannesSchaub
Karl Richter
-4

matrizes armazenam seu tamanho em uma variável local chamada 'length'. Dada uma matriz chamada "a", você pode usar o seguinte para fazer referência ao último índice sem conhecer o valor do índice

a [a.length-1]

para atribuir um valor de 5 a este último índice, você usaria:

a [a.length-1] = 5;

closeab
fonte
Este ArrayListnão é um array.
glee8e
-6

Alternativa usando a API de Stream:

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

Resulta em um opcional do último elemento.

Terran
fonte
-7

No Kotlin, você pode usar o método last:

val lastItem = list.last()
Ollie
fonte
10
No entanto, isto é java
Jachdich 03/10/19
4
Uma das idéias por trás da criação do Kotlin era cobrir os pequenos lados desconfortáveis ​​do Java. Então, acho que faz sentido recomendar considerar o Kotlin, pelo menos para as partes do aplicativo que fazem análise de dados.
Eerik Sven Puudist