Як отримати останнє значення ArrayList


597

Як я можу отримати останнє значення ArrayList?

Я не знаю останнього індексу ArrayList.


164
Я підтримав це питання, тому що мені було цікаво, чому немає такого способу, як: getLastItem (), і прийшов подивитися, чи є відповідь. list.size () - 1 не дуже.
Nuno Gonçalves

2
@ NunoGonçalves Ви завжди можете підкласирувати його!
Тім

12
Ви завжди можете використовувати LinkedList, який має методgetLast()
ssedano

6
Пов'язаний список додає цілу купу накладних витрат. Використовуйте Guava, як показано нижче: lastElement = Iterables.getLast (iterableList); АБО просто індексуйте дзвінок get () з розміром () - 1. Це не так потворно порівняно з використанням зв'язаного списку, коли його не потрібно. Звичайні застереження застосовуються щодо умов виключення - див. Javadoc ArrayList.
RichieHH

10
Використання list.size () -1 не дуже, але використання API сторонніх розробників лише для цього гірше
Javo

Відповіді:


692

Далі йде частина Listінтерфейсу (який реалізує ArrayList):

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

E- тип елемента. Якщо список порожній, getвикидає анну IndexOutOfBoundsException. Ви можете знайти всю документацію API тут .


5
Чи це спричинить ітерацію списку? Це не здається мені дуже ефективним. Я походжу з C ++, де на об’єкті списку існують фактичні фронт () та задній () методи, які реалізуються внутрішньо із посиланнями на голову та хвіст. Чи є подібний механізм у Java?
Брейді

26
Не буде працювати. що робити, якщо список порожній, list.size () поверне 0. і ви отримаєте list.get (-1);
FRR

18
@feresr так. Він хоче отримати останнє значення у списку. Звичайно, це означає, що розмір () дорівнює> 0. Це було б справедливо для будь-якої реалізації. Прочитавши до кінця, ви заощадили б час, який вам потрібен, щоб написати коментар, і мій час для відповіді :) Моя відповідь в кінці говорить "Якщо список порожній, викидайте IndexOutOfBoundsException"
Йоханнес Шауб - ліб

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

9
Я не можу зрозуміти, чому вони вирішили застосувати простий lastElement()метод для своїх, Vectorале не для ArrayList. Що з цією неузгодженістю?
Стефан Димитров

211

У ванільній Java немає елегантного способу.

Google Guava

Бібліотека Google Guava чудова - перевірте їх Iterablesклас . Цей метод викине a, 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

Я використовую клас мікро-утиліти для отримання останнього (і першого) елемента списку:

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
Просто використовуйте гуаву. Не заново
вигадуйте

15
@ClickUpvote Використання Guava лише для одного крихітного методу у багатьох випадках є надмірним. Моя відповідь - для людей, які шукають рішення ванільної Java . Якщо ви вже використовуєте Guava у своєму проекті, подивіться іншу відповідь на рішення, засноване на Guava.
користувач11153

5
Якщо ви не використовуєте гуаву, ви закінчите писати багато класів корисних програм, як цей.
Клацніть Upvote

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

2
isEmptyне перевіряє, чи є список порожнім і таким повинен бути, isNullOrEmptyі це не є частиною питання - або ви намагаєтеся покращити набір відповідей, або надаєте класи корисності (які є повторним винаходом).
Карл Ріхтер

10

size()Метод повертає кількість елементів в ArrayList. Значення індексу елементів проходять 0через (size()-1), тому ви б використали myArrayList.get(myArrayList.size()-1)для отримання останнього елемента.



5

Якщо ви можете, поміняти ArrayListдля ArrayDeque, який має зручні методи , як removeLast.


1
Це означає принаймні лінійну вартість порівняно з постійною вартістю прямого доступу, але варто згадати.
Карл Ріхтер

@KarlRichter Так. Це відповідає відсутності таких методів, як get (int) в інтерфейсі ArrayDeque. Це те, що я мав намір запропонувати "Якщо можете"; якщо до списку немає доступу до індексу, можливо, він не повинен бути списком.
Джон Глассмер

5

Немає елегантного способу отримання останнього елемента списку на 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інтерфейс. Чому ви хочете викликати метод, що повертає Список, якщо вас цікавить лише останній елемент? Я не пам’ятаю, чи бачив це взагалі раніше.
Доріан Грей

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

Я не бачу, де це досить поширене явище, і якщо воно є, то краще скористайтеся ArrayDequeнатомість.
Доріан Грей

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

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, ви можете отримати доступ до першого елемента та останнього просто getFirst()та getLast()(якщо ви хочете більш чистий спосіб, ніж розмір () -1 та отримати (0))

Впровадження

Оголосити LinkedList

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

Тоді це методи, якими ви можете скористатися, щоб отримати те, що ви хочете, в даному випадку мова йде про ПЕРШИЙ та ОСТАНИЙ елемент списку

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

якщо поданий список порожній, він видає an IndexOutOfBoundsException


1
java.util.Collections#reverseробить це теж.
RoBeaToZ

1
@RoBeaToZ, це робить, але він змінює початковий список, повторюючи його і повертає недійсним, тому не вважає, що підходить для цієї мети.
pero_hero

0

Оскільки індексація в ArrayList починається з 0 і закінчується на одному місці перед фактичним розміром, отже правильним твердженням для повернення останнього елемента масиву буде:

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

Наприклад:

якщо розмір списку масиву дорівнює 5, то розмір-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

масиви зберігають їх розмір у локальній змінній під назвою "length". Враховуючи масив з назвою "a", ви можете використовувати наступне для посилання на останній індекс, не знаючи значення індексу

a [a.length-1]

щоб присвоїти цьому останньому індексу значення 5, яке ви використовували:

a [a.length-1] = 5;


Це ArrayListне масив.
glee8e

-6

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

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

Результати за бажанням останнього елемента.


-7

У Котліні ви можете використовувати метод last:

val lastItem = list.last()

10
Це, однак, Java
Jachdich

4
Однією з ідей створення Котліна було висвітлити маленькі незручні сторони Java. Тому я вважаю, що має сенс рекомендувати розглянути питання щодо Котліна, принаймні для частин програми, які роблять аналізи даних.
Ерік Свен Пуудист
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.