Làm thế nào để có được giá trị cuối cùng của một ArrayList


597

Làm thế nào tôi có thể nhận được giá trị cuối cùng của một ArrayList?

Tôi không biết chỉ mục cuối cùng của ArrayList.


164
Tôi nêu lên câu hỏi này, vì tôi đã tự hỏi tại sao không có phương pháp nào như: getLastItem () và đến để xem liệu có câu trả lời không. list.size () - 1 không đẹp.
Nuno Gonçalves

2
@ NunoGonçalves Bạn luôn có thể phân lớp nó!
Tim

12
Bạn luôn có thể sử dụng LinkedList có phương thứcgetLast()
ssedano

6
Danh sách liên kết nó thêm một đống chi phí. Sử dụng Guava như hiển thị bên dưới: lastEuity = Iterables.getLast (iterableList); HOẶC chỉ cần lập chỉ mục một cuộc gọi get () với kích thước () - 1. Nó không xấu so với việc sử dụng danh sách được liên kết khi không cần thiết. Hãy cẩn thận thông thường áp dụng liên quan đến các điều kiện ngoại lệ - xem javadoc ArrayList.
RichieHH

10
Sử dụng list.size () -1 không đẹp, nhưng sử dụng API của bên thứ 3 chỉ vì điều này còn tệ hơn
Javo

Câu trả lời:


692

Sau đây là một phần của Listgiao diện (mà ArrayList thực hiện):

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

Elà loại phần tử. Nếu danh sách trống, getném một IndexOutOfBoundsException. Bạn có thể tìm thấy toàn bộ tài liệu API tại đây .


5
Điều này sẽ gây ra một sự lặp lại của danh sách? Điều đó dường như không hiệu quả đối với tôi. Tôi đến từ C ++, nơi có các phương thức front () và back () thực tế trên đối tượng danh sách, được triển khai bên trong với các tham chiếu head và tail. Có một cơ chế tương tự trong Java?
Brady

26
Sẽ không làm việc. nếu danh sách trống, list.size () sẽ trả về 0. và bạn sẽ kết thúc với list.get (-1);
FRR

18
@feresr hả. Anh ấy muốn có được giá trị cuối cùng trong danh sách. Tất nhiên điều đó ngụ ý rằng kích thước () là> 0. Điều đó sẽ đúng với bất kỳ loại thực hiện nào. Đọc đến cuối sẽ tiết kiệm thời gian bạn cần để viết bình luận và thời gian trả lời của tôi :) Câu trả lời của tôi nói ở cuối "Nếu danh sách trống, hãy ném IndexOutOfBoundException"
Johannes Schaub - litb

16
@Brady nó sẽ không gây ra phép lặp O (n) cho ArrayList, vì như bạn có thể đoán, nó được hỗ trợ bởi một mảng. Vì vậy, một get (<index>) đơn giản chỉ dẫn đến việc truy xuất thời gian không đổi từ một mảng. (Nguồn JDK xác nhận điều này) Đối với các triển khai danh sách khác, điều này không được đảm bảo, vì vậy, ví dụ, LinkedList có phương thức getLast () là thời gian không đổi.
Peter

9
Tôi không thể hiểu tại sao họ quyết định thực hiện một lastElement()phương pháp đơn giản cho họ Vectornhưng không phải cho ArrayList. Có chuyện gì với sự mâu thuẫn đó?
Stefan Dimitrov

211

Không có một cách thanh lịch trong Java vani.

Quả ổi

Các Google Ổi thư viện là rất tốt - kiểm tra của họ Iterableslớp . Phương pháp này sẽ đưa ra NoSuchElementExceptionnếu danh sách trống, trái ngược với một IndexOutOfBoundsException, như với size()-1cách tiếp cận thông thường - tôi thấy NoSuchElementExceptionđẹp hơn nhiều hoặc khả năng chỉ định mặc định:

lastElement = Iterables.getLast(iterableList);

Bạn cũng có thể cung cấp một giá trị mặc định nếu danh sách trống, thay vì một ngoại lệ:

lastElement = Iterables.getLast(iterableList, null);

hoặc, nếu bạn đang sử dụng Tùy chọn:

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

3
Bạn có biết phương pháp này thực hiện bước tuyến tính qua danh sách để tìm phần tử cuối cùng không?
Billman

5
@BillMan Trong trường hợp Hashset có, trong trường hợp ArrayList không.
Simon

6
Bạn nên thêm Iterables.getLastkiểm tra xem có RandomAccessđược triển khai hay không và do đó nếu nó được truy cập vào mục trong O (1).
Karl Richter

1
Thay vì Option, bạn có thể sử dụng Java nguyên gốc Optional. Nó cũng sẽ sạch hơn một chút : lastElement = Optional.ofNullable(lastElementRaw);.
Người trợ giúp nhỏ

186

điều này nên làm điều đó:

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

29
không có cách nào đẹp để làm điều đó? : /
kommradHomer

6
Bạn có lẽ ít nhất nên chứng minh việc gán nó ... ArrayList.get không ảnh hưởng đến phụ.
Stony Stubbs

Có quá nhỏ để chỉ ra ở trên không gán / trả lại bất cứ điều gì?
Brian Agnew

Nếu một ArrayList chỉ có một bản ghi thì có ngoại lệ xảy ra. Điều gì sẽ là giải pháp?
hasnain_ahmad

2
@hasnain_ahmad, khi ArraList có 1 phần tử, nó hoạt động chính xác, bạn nên lo lắng về ArrayList và ArrayList không được khởi tạo với bản ghi bằng không. Và câu trả lời này xử lý cả hai trường hợp
Farid

27

Tôi sử dụng lớp micro-produc để lấy phần tử cuối cùng (và đầu tiên) của danh sách:

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

Hơi linh hoạt hơn:

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
Chỉ cần sử dụng ổi. Không phát minh lại
Nhấp vào Upvote

15
@ClickUpvote Sử dụng Guava cho chỉ một phương thức nhỏ trong nhiều trường hợp là quá mức cần thiết. Câu trả lời của tôi là dành cho những người tìm kiếm giải pháp Java vani . Nếu bạn đã sử dụng Guava trong dự án của mình, hãy xem câu trả lời khác cho giải pháp dựa trên Guava.
dùng11153

5
Nếu bạn không sử dụng ổi, cuối cùng bạn sẽ viết rất nhiều lớp tiện ích như thế này.
Nhấp vào Upvote

6
Đôi khi, việc cho phép thêm thư viện của bên thứ ba có thể liên quan nhiều hơn nhiều so với việc thêm một lớp Java riêng. Ví dụ: hợp đồng chính phủ nơi họ giới hạn và sàng lọc các thư viện của bên thứ ba.
Dave Jarvis

2
isEmptykhông kiểm tra xem danh sách có trống hay không và do đó isNullOrEmptykhông phải là một phần của câu hỏi - hoặc bạn cố gắng nâng cao bộ câu trả lời hoặc bạn cung cấp cho bạn các lớp tiện ích (là một phát minh lại).
Karl Richter

10

Các size()phương thức trả về số phần tử trong ArrayList. Các giá trị chỉ mục của các phần tử là 0thông qua (size()-1), vì vậy bạn sẽ sử dụng myArrayList.get(myArrayList.size()-1)để truy xuất phần tử cuối cùng.



6

Không có cách nào thanh lịch để lấy phần tử cuối cùng của danh sách trong Java (so với ví dụ items[-1]trong Python).

Bạn phải sử dụng list.get(list.size()-1).

Khi làm việc với các danh sách thu được bằng các cuộc gọi phương thức phức tạp, cách giải quyết nằm ở biến tạm thời:

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

Đây là tùy chọn duy nhất để tránh phiên bản xấu xí và thường đắt tiền hoặc thậm chí không hoạt động:

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

Sẽ thật tuyệt nếu sửa lỗi cho lỗi thiết kế này được đưa vào API Java.


Tôi không thấy một "lỗ hổng thiết kế" ở đây, những gì bạn đưa ra là một trường hợp sử dụng hiếm hoi không đáng để thêm vào Listgiao diện. Tại sao bạn muốn gọi một phương thức trả về Danh sách, nếu bạn chỉ quan tâm đến phần tử cuối cùng? Tôi không nhớ là tôi đã thấy điều đó trước đây.
Dorian Gray

1
@DorianGray Đọc phần tử cuối cùng từ danh sách là một hoạt động khá phổ biến và list.get(list.size()-1)là ví dụ tối thiểu cho thấy vấn đề. Tôi đồng ý rằng các ví dụ "nâng cao" có thể gây tranh cãi và có thể là một trường hợp cạnh, tôi chỉ muốn chỉ ra làm thế nào vấn đề có thể lan truyền thêm. Hãy giả sử rằng lớp của someObjectnước ngoài, đến từ thư viện bên ngoài.
Tregoreg

Tôi không thấy nơi này là khá phổ biến, và nếu nó là, tốt hơn bạn nên sử dụng ArrayDeque.
Dorian Gray

@DorianGray Câu hỏi này có rất nhiều quan điểm và quan điểm, vì vậy có rất nhiều người quan tâm đến việc nhận được giá trị cuối cùng của một ArrayList.
Tregoreg

5

Nếu bạn có thể, trao đổi ArrayListcho một ArrayDeque, có phương pháp thuận tiện như removeLast.


1
Điều này có nghĩa là ít nhất chi phí tuyến tính so với chi phí không đổi cho truy cập trực tiếp, nhưng đáng nói.
Karl Richter

@KarlRichter Có. Điều này tương ứng với sự vắng mặt của các phương thức như get (int) trong giao diện của ArrayDeque. Đây là những gì tôi muốn đề xuất bởi "Nếu bạn có thể"; nếu danh sách không được truy cập bởi chỉ mục, thì có lẽ nó không cần phải là Danh sách.
John Glassmyer

3

Như đã nêu trong giải pháp, nếu Listtrống thì an IndexOutOfBoundsExceptionđược ném. Một giải pháp tốt hơn là sử dụng Optionalloại:

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

Như bạn mong đợi, phần tử cuối cùng của danh sách được trả về dưới dạng Optional:

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

Nó cũng xử lý một cách duyên dáng với các danh sách trống:

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

2

Nếu bạn sử dụng LinkedList thay thế, bạn có thể truy cập phần tử đầu tiên và phần tử cuối cùng chỉ getFirst()getLast()(nếu bạn muốn một cách sạch hơn kích thước () -1 và get (0))

Thực hiện

Khai báo một danh sách liên kết

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

Sau đó, đây là các phương pháp bạn có thể sử dụng để có được những gì bạn muốn, trong trường hợp này chúng ta đang nói về yếu tố FIRSTLAST của danh sách

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

Vì vậy, sau đó bạn có thể sử dụng

mLinkedList.getLast(); 

để có được yếu tố cuối cùng của danh sách.


1

ổi cung cấp một cách khác để có được yếu tố cuối cùng từ a List:

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

nếu danh sách được cung cấp trống, nó sẽ ném IndexOutOfBoundsException


1
java.util.Collections#reversenó cũng vậy
RoBeaToZ

1
@RoBeaToZ, nhưng nó thay đổi danh sách ban đầu bằng cách lặp qua nó và trả về khoảng trống, vì vậy nó không phù hợp với mục đích này.
pero_hero

0

Vì việc lập chỉ mục trong ArrayList bắt đầu từ 0 và kết thúc một vị trí trước kích thước thực tế do đó câu lệnh đúng để trả về phần tử danh sách mảng cuối cùng sẽ là:

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

Ví dụ:

nếu kích thước của danh sách mảng là 5, thì size-1 = 4 sẽ trả về phần tử mảng cuối cùng.


-1

Mục cuối cùng trong danh sách là list.size() - 1. Bộ sưu tập được hỗ trợ bởi một mảng và các mảng bắt đầu ở chỉ số 0.

Vì vậy, phần tử 1 trong danh sách nằm ở chỉ số 0 trong mảng

Phần tử 2 trong danh sách nằm ở chỉ số 1 trong mảng

Phần tử 3 trong danh sách nằm ở chỉ số 2 trong mảng

và như thế..


3
không có giá trị bổ sung nào cho câu trả lời trước đó của @ JohannesSchaub
Karl Richter

-3

Làm thế nào về điều này .. Một nơi nào đó trong lớp của bạn ...

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

Nếu bạn sửa đổi danh sách của mình, sau đó sử dụng listIterator()và lặp lại từ chỉ mục cuối cùng ( size()-1tương ứng). Nếu bạn thất bại một lần nữa, kiểm tra cấu trúc danh sách của bạn.


-3

Tất cả những gì bạn cần làm là sử dụng size () để lấy giá trị cuối cùng của Arraylist. Dành cho người cũ nếu bạn ArrayList các số nguyên, thì để có được giá trị cuối cùng, bạn sẽ phải

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

Hãy nhớ rằng, các phần tử trong Arraylist có thể được truy cập bằng các giá trị chỉ mục. Do đó, ArrayLists thường được sử dụng để tìm kiếm các mục.


4
không có giá trị bổ sung nào cho câu trả lời trước đó của @ JohannesSchaub
Karl Richter

-4

mảng lưu trữ kích thước của chúng trong một biến cục bộ gọi là 'chiều dài'. Đưa ra một mảng có tên là "a", bạn có thể sử dụng thông tin sau để tham chiếu chỉ mục cuối cùng mà không cần biết giá trị chỉ mục

một [a.length-1]

để gán giá trị 5 cho chỉ mục cuối cùng này, bạn sẽ sử dụng:

a [a.length-1] = 5;


Đây ArrayListkhông phải là một mảng.
glee8e

-6

Thay thế bằng API Stream:

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

Kết quả trong một tùy chọn của yếu tố cuối cùng.


-7

Trong Kotlin, bạn có thể sử dụng phương thức last:

val lastItem = list.last()

10
Đây là java tuy nhiên
Jachdich

4
Một trong những ý tưởng đằng sau việc tạo ra Kotlin là đề cập đến những khía cạnh không thoải mái của Java. Vì vậy, tôi nghĩ sẽ hợp lý khi khuyên bạn nên xem xét Kotlin, ít nhất là đối với các phần của ứng dụng làm dữ liệu analasys.
Eerik Sven Puudist
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.