Как получить последнее значение ArrayList


598

Как я могу получить последнее значение ArrayList?

Я не знаю последний индекс ArrayList.


165
Я поднял этот вопрос, потому что мне было интересно, почему нет такого метода, как: getLastItem (), и пришел посмотреть, был ли ответ. list.size () - 1 это не красиво.
Нуно Гонсалвеш

2
@ NunoGonçalves Вы всегда можете подкласс его!
Тим

12
Вы всегда можете использовать LinkedList, у которого есть методgetLast()
ssedano

6
Связанный листинг добавляет кучу накладных расходов. Используйте Guava, как показано ниже: lastElement = Iterables.getLast (iterableList); ИЛИ просто индексировать вызов get () с помощью size () - 1. Это не так страшно по сравнению с использованием связанного списка, когда его не требуется. Обычные предостережения применяются в отношении условий исключения - см. Javadoc ArrayList.
RichieHH

10
Использование list.size () -1 не очень, но с использованием 3 участника API только для этого хуже
Javo

Ответы:


693

Следующее является частью Listинтерфейса (который реализует ArrayList):

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

Eэто тип элемента. Если список пуст, getвыдает IndexOutOfBoundsException. Вы можете найти всю документацию по API здесь .


5
Это вызовет итерацию списка? Это не кажется мне очень эффективным. Я пришел из C ++, где есть реальные методы front () и back () в объекте list, которые внутренне реализованы с использованием ссылок head и tail. Есть ли подобный механизм в Java?
Брэди

26
Не сработает что если список пуст, list.size () вернет 0. и вы получите list.get (-1);
FRR

18
@ Feresr да. Он хочет получить последнее значение в списке. Конечно, это означает, что size ()> 0. Это было бы верно для любой реализации. Чтение до конца сэкономило бы время, необходимое для написания комментария, и время для ответа :) В конце мой ответ говорит: «Если список пуст, get создает исключение IndexOutOfBoundsException»
Йоханнес Шауб - litb

16
@Brady это не вызовет O (n) итерацию для ArrayList, потому что, как вы можете догадаться, он поддерживается массивом. Таким образом, простое получение (<index>) просто приводит к извлечению из массива с постоянным временем. (Источник JDK подтверждает это). Для других реализаций списков это не гарантируется, поэтому, например, LinkedList имеет метод getLast (), который имеет постоянное время.
Питер

9
Я не могу понять, почему они решили реализовать простой lastElement()метод для их, Vectorно не для ArrayList. Что случилось с этим несоответствием?
Стефан Димитров

211

В ванильной Java нет элегантного способа.

Google Guava

Библиотека Google Guava великолепна - проверьте их Iterablesкласс . Этот метод будет выдавать, NoSuchElementExceptionесли список пуст, в отличие IndexOutOfBoundsExceptionот обычного size()-1подхода - я считаю, что NoSuchElementExceptionгораздо лучше, или возможность указать значение по умолчанию:

lastElement = Iterables.getLast(iterableList);

Вы также можете указать значение по умолчанию, если список пуст, вместо исключения:

lastElement = Iterables.getLast(iterableList, null);

или, если вы используете параметры:

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

3
Знаете ли вы, если этот метод делает линейный обход списка, чтобы найти последний элемент?
BillMan

5
@BillMan В случае HashSet да, в случае ArrayList нет.
Саймон

6
Вы должны добавить эту Iterables.getLastпроверку, RandomAccessреализована ли она и, следовательно, имеет ли она доступ к элементу в O (1).
Карл Рихтер

1
Вместо этого Optionвы можете использовать нативную Java Optional. Это также будет немного чище lastElement = Optional.ofNullable(lastElementRaw);.
Маленький помощник

186

это должно сделать это:

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

29
разве нет никакого изящного способа сделать это? : /
kommradHomer

6
Вы, вероятно, должны хотя бы продемонстрировать его назначение ... ArrayList.get не имеет побочных эффектов.
Энтони Стаббс

Это слишком мелко, чтобы указать, что выше не присваивает / не возвращает ничего?
Брайан Агнью

Если ArrayList имеет только одну запись, то происходит исключение. Каким будет решение?
hasnain_ahmad

2
@hasnain_ahmad, когда у ArraList есть 1 элемент, он работает правильно, вам следует беспокоиться о неинициализированных ArrayList и ArrayList с нулевой записью. И этот ответ касается обоих случаев
Фарид

27

Я использую класс micro-util для получения последнего (и первого) элемента списка:

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

Чуть более гибкий:

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
Просто используйте гуаву. Не изобретайте заново
нажмите Upvote

15
@ClickUpvote Использование Гуавы только для одного крошечного метода во многих случаях является излишним. Мой ответ для людей, которые ищут ванильное решение Java . Если вы уже используете Guava в своем проекте, см. Другой ответ для решения на основе Guava.
user11153

5
Если вы не используете guava, вы в конечном итоге напишите много полезных классов, подобных этому.
Нажмите Upvote

6
Иногда получение разрешения на добавление сторонней библиотеки может быть гораздо более сложным, чем добавление одного нативного Java-класса. Например, государственные контракты, где они ограничивают и проверяют сторонние библиотеки.
Дейв Джарвис

2
isEmptyне проверяет, является ли список пустым и должен ли он быть таким, isNullOrEmptyи это не является частью вопроса - либо вы пытаетесь расширить набор ответов, либо предоставляете вам служебные классы (которые являются переизобретением).
Карл Рихтер

10

size()Метод возвращает количество элементов в ArrayList. Индексные значения элементов являются 0сквозными (size()-1), поэтому вы должны использовать myArrayList.get(myArrayList.size()-1)для получения последнего элемента.



6

В Java нет элегантного способа получить последний элемент списка (по сравнению, например, items[-1]с Python).

Вы должны использовать list.get(list.size()-1).

При работе со списками, полученными с помощью сложных вызовов методов, обходной путь заключается во временной переменной:

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

Это единственный вариант избежать уродливой и зачастую дорогой или даже не работающей версии:

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

Было бы хорошо, если бы исправление для этого недостатка дизайна было введено в Java API.


Я не вижу здесь «недостатка дизайна», то, что вы упоминаете, - это редкий случай использования, который не стоит добавлять в Listинтерфейс. Зачем вам вызывать метод, возвращающий List, если вас интересует только последний элемент? Я не помню, я видел это вообще раньше.
Дориан Грей

1
@DorianGray Чтение последнего элемента из списка - довольно распространенная операция и list.get(list.size()-1)является минимальным примером, показывающим проблему. Я согласен, что «продвинутые» примеры могут быть спорными и, возможно, крайним случаем, я просто хотел показать, как проблема может распространяться дальше. Предположим, что класс someObjectиностранный, пришедший из внешней библиотеки.
Трегорег

Я не вижу, где это довольно распространено, и если это так, лучше использовать ArrayDequeвместо этого.
Дориан Грей

@DorianGray У этого вопроса много откликов и мнений, поэтому есть много людей, заинтересованных в получении последнего значения ArrayList.
Трегорег

5

Если вы можете, замените ArrayListдля ArrayDeque, который имеет удобные методы, как removeLast.


1
Это означает как минимум линейную стоимость по сравнению с постоянными затратами на прямой доступ, но стоит упомянуть.
Карл Рихтер

@KarlRichter Да. Это соответствует отсутствию методов типа get (int) в интерфейсе ArrayDeque. Это то, что я хотел сказать, «Если можешь»; если список не доступен по индексу, то, возможно, это не обязательно должен быть список.
Джон Глассмайер

3

Как указано в решении, если Listпусто, то IndexOutOfBoundsExceptionвыбрасывается. Лучшее решение - использовать Optionalтип:

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

Как и следовало ожидать, последний элемент списка возвращается как Optional:

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

Это также изящно имеет дело с пустыми списками:

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

2

Если вместо этого вы используете LinkedList, вы можете получить доступ к первому и последнему элементу с помощью just getFirst()и getLast()(если вам нужен более чистый способ, чем size () -1 и get (0))

Реализация

Объявить LinkedList

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

Тогда это методы, которые вы можете использовать, чтобы получить то, что вы хотите, в данном случае мы говорим о элементах FIRST и LAST списка

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

Итак, тогда вы можете использовать

mLinkedList.getLast(); 

чтобы получить последний элемент списка.


1

guava предоставляет другой способ получить последний элемент из List:

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

если предоставленный список пуст, он бросает IndexOutOfBoundsException


1
java.util.Collections#reverseделает это тоже.
RoBeaToZ

1
@RoBeaToZ, он делает, но он изменяет исходный список, перебирая его и возвращает void, поэтому он не подходит для этой цели.
pero_hero

0

Поскольку индексирование в ArrayList начинается с 0 и заканчивается на одно место перед фактическим размером, следовательно, правильный оператор для возврата последнего элемента arraylist будет выглядеть так:

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

Например:

если размер списка массивов равен 5, то size-1 = 4 вернет последний элемент массива.


-1

Последний элемент в списке list.size() - 1. Коллекция поддерживается массивом, а массивы начинаются с индекса 0.

Таким образом, элемент 1 в списке имеет индекс 0 в массиве.

Элемент 2 в списке находится по индексу 1 в массиве

Элемент 3 в списке находится по индексу 2 в массиве

и так далее..


3
нет никакого дополнительного значения к более раннему ответу @ JohannesSchaub
Карл Рихтер

-3

Как насчет этого .. Где-то в вашем классе ...

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

Если вы измените свой список, используйте listIterator()и итерируйте последний индекс (то есть size()-1соответственно). Если вы снова потерпите неудачу, проверьте структуру списка.


-3

Все, что вам нужно сделать, это использовать size (), чтобы получить последнее значение Arraylist. Например если вы ArrayList из целых чисел, то для получения последнего значения вам придется

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

Помните, что к элементам в Arraylist можно получить доступ, используя значения индекса. Поэтому ArrayLists обычно используются для поиска элементов.


4
нет никакого дополнительного значения к более раннему ответу @ JohannesSchaub
Карл Рихтер

-4

Массивы хранят свой размер в локальной переменной, называемой «длина». Имея массив с именем "a", вы можете использовать следующее для ссылки на последний индекс, не зная значения индекса

а [a.length-1]

чтобы присвоить значение 5 этому последнему индексу, который вы бы использовали:

а [a.length-1] = 5;


Это ArrayListне массив.
glee8e

-6

Альтернатива с использованием Stream API:

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

Результатом является необязательный последний элемент.


-7

В Kotlin вы можете использовать метод last:

val lastItem = list.last()

10
Это
Ява

4
Одна из идей создания Kotlin заключалась в том, чтобы охватить небольшие неудобные стороны Java. Поэтому я думаю, что имеет смысл рекомендовать рассмотреть Kotlin, по крайней мере, для тех частей приложения, которые выполняют анализ данных.
Eerik Sven Puudist
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.