ChatGPT解决这个技术问题 Extra ChatGPT

How to get the last value of an ArrayList

How can I get the last value of an ArrayList?

I upvoted this question, because I was wondering why there's no such a method like: getLastItem() and came to see if there was an answer. list.size() - 1 is not pretty.
@NunoGonçalves You can always subclass it!
You could always use a LinkedList which has the method getLast()
Linked listing it adds a whole heap of overhead. Use Guava as shown below : lastElement = Iterables.getLast(iterableList); OR simply index a get() call with size() - 1. Its not that ugly compared to using a linked list when its not required. Usual caveats apply regarding exception conditions - see the ArrayList javadoc.
Using list.size() -1 is not pretty, but using a 3rd party API just for this is worse

J
Jarvis

The following is part of the List interface (which ArrayList implements):

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

E is the element type. If the list is empty, get throws an IndexOutOfBoundsException. You can find the whole API documentation here.


Will this cause an iteration of the list? That doesnt seem very efficient to me. I come from C++, where there are actual front() and back() methods on the list object, that are internally implemented with head and tail references. Is there a similar mechanism in Java?
Won't work. what if the list is empty, list.size() will return 0. and you'll end up with list.get(-1);
@feresr huh. He wants to get the last value in the list. Of course that implies that size() is > 0. That would be true for any sort of implementation. Reading through to the end would have saved the time you needed to write your comment and my time for answering :) My answer says at the end "If the list is empty, get throws an IndexOutOfBoundsException"
@Brady it won't cause an O(n) iteration for an ArrayList, because as you can guess, it's backed by an array. So a simple get() just results in a constant-time retrieve from an array. (JDK source confirms this) For other list implementations, this isn't guaranteed, so for example, LinkedList has a getLast() method which is constant-time.
I can't understand why they decided to implement a simple lastElement() method for their Vector but not for ArrayList. What's up with that inconsistency?
O
Olivier Grégoire

There isn't an elegant way in vanilla Java.

Google Guava

The Google Guava library is great - check out their Iterables class. This method will throw a NoSuchElementException if the list is empty, as opposed to an IndexOutOfBoundsException, as with the typical size()-1 approach - I find a NoSuchElementException much nicer, or the ability to specify a default:

lastElement = Iterables.getLast(iterableList);

You can also provide a default value if the list is empty, instead of an exception:

lastElement = Iterables.getLast(iterableList, null);

or, if you're using Options:

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

Do you know if this this method do a linear walk through the list to find the last element?
@BillMan In the case of HashSet yes, in the case of ArrayList no.
You should add that Iterables.getLast check whether RandomAccess is implemented and therefore if it is accesses the item in O(1).
Instead of Option, you can use the native Java Optional. It will also be a bit cleaner: lastElement = Optional.ofNullable(lastElementRaw);.
C
Christian

this should do it:

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

is there no sleek way to do it ? :/
You should probably at least demonstrate assigning it... ArrayList.get is side-affect free.
Is it too petty to indicate the above doesn't assign/return anything ?
If an ArrayList only have one record then there is exception occurred. What will be the solution?
@hasnain_ahmad, when ArraList has 1 element it works properly, you should worry about non-initialized ArrayList and ArrayList with zero record. And this answer handles both cases
D
Dave Jarvis

I use micro-util class for getting last (and first) element of list:

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

Slightly more 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();
  }
}

Just use guava. Don't re-invent
@ClickUpvote Using Guava for just one tiny method is in many cases an overkill. My answer is for people looking for vanilla Java solution. If you are already using Guava in your project, see other answer for Guava-based solution.
If you don't use guava, you end up writing lots of utility classes like this one.
Sometimes getting permission to add a third-party library can be a lot more involved than adding a single native Java class. For example, government contracts where they limit and screen third-party libraries.
isEmpty doesn't check whether the list is empty and should thus be isNullOrEmpty and that's not part of the question - either you try to enhance the set of answers or you provide you utility classes (which are a re-invention).
K
Ken Paul

The size() method returns the number of elements in the ArrayList. The index values of the elements are 0 through (size()-1), so you would use myArrayList.get(myArrayList.size()-1) to retrieve the last element.


T
Tregoreg

There is no elegant way of getting the last element of a list in Java (compared to e.g. items[-1] in Python).

You have to use list.get(list.size()-1).

When working with lists obtained by complicated method calls, the workaround lies in temporary variable:

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

This is the only option to avoid ugly and often expensive or even not working version:

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

It would be nice if fix for this design flaw was introduced to Java API.


I do not see a "design flaw" here, what you bring up is a rare use case that's not worth to be added to the List interface. Why would you want to call a method returning a List, if you're only interested in the last element? I do not remember I have seen that at all before.
@DorianGray Reading last element from a list is a pretty common operation and list.get(list.size()-1) is the minimal example showing the issue. I agree that the "advanced" examples may be controversial and possibly an edge case, I just wanted to show how the issue can further propagate. Let's assume that the class of someObject is foreign, coming from external library.
I do not see where this is pretty common, and if it is, you better use ArrayDeque instead.
@DorianGray This question has a lot of upvotes and views, so there is a lot of people interested in getting the last value of an ArrayList.
L
Luis Vieira Damiani

Using lambdas:

Function<ArrayList<T>, T> getLast = a -> a.get(a.size() - 1);

J
John Glassmyer

If you can, swap out the ArrayList for an ArrayDeque, which has convenient methods like removeLast.


This means at least linear cost in comparison to constant cost for direct access, but worth mentioning.
@KarlRichter Yes. This corresponds with the absence of methods like get(int) in ArrayDeque's interface. This is what I meant to suggest by "If you can"; if the list is not being accessed by index, then perhaps it doesn't need to be a List.
C
Colin Breame

As stated in the solution, if the List is empty then an IndexOutOfBoundsException is thrown. A better solution is to use the Optional type:

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

As you'd expect, the last element of the list is returned as an Optional:

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

It also deals gracefully with empty lists as well:

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

G
Gastón Saillén

If you use a LinkedList instead , you can access the first element and the last one with just getFirst() and getLast() (if you want a cleaner way than size() -1 and get(0))

Implementation

Declare a LinkedList

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

Then this are the methods you can use to get what you want, in this case we are talking about FIRST and LAST element of a list

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

So , then you can use

mLinkedList.getLast(); 

to get the last element of the list.


Best response here!
C
Craigo

A one liner that takes into account empty lists would be:

T lastItem = list.size() == 0 ? null : list.get(list.size() - 1);

Or if you don't like null values (and performance isn't an issue):

Optional<T> lastItem = list.stream().reduce((first, second) -> second);

J
Jacob van Lingen

In case you have a Spring project, you can also use the CollectionUtils.lastElement from Spring (javadoc), so you don't need to add an extra dependency like Google Guava.

It is null-safe so if you pass null, you will simply receive null in return. Be careful when handling the response though.

Here are somes unit test to demonstrate them:

@Test
void lastElementOfList() {
    var names = List.of("John", "Jane");

    var lastName = CollectionUtils.lastElement(names);

    then(lastName)
        .as("Expected Jane to be the last name in the list")
        .isEqualTo("Jane");
}

@Test
void lastElementOfSet() {
    var names = new TreeSet<>(Set.of("Jane", "John", "James"));

    var lastName = CollectionUtils.lastElement(names);

    then(lastName)
        .as("Expected John to be the last name in the list")
        .isEqualTo("John");
}

Note: org.assertj.core.api.BDDAssertions#then(java.lang.String) is used for assertions.


s
shravyaverma

Since the indexing in ArrayList starts from 0 and ends one place before the actual size hence the correct statement to return the last arraylist element would be:

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

For example:

if size of array list is 5, then size-1 = 4 would return the last array element.


p
pero_hero

guava provides another way to obtain the last element from a List:

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

if the provided list is empty it throws an IndexOutOfBoundsException


java.util.Collections#reverse does it, too.
@RoBeaToZ, it does but it changes the original list by iterating through it and returns void, so it doesn't deem to fit for this purpose.
That's pretty expensive for just getting one element. Imagine your list has 1.000.000 entries or so.
@philburns this call is in O(1) regardless of the list size
M
Med Sep

This worked for me.

private ArrayList<String> meals;
public String take(){
  return meals.remove(meals.size()-1);
}

M
MircoProgram

The last item in the list is list.size() - 1. The collection is backed by an array and arrays start at index 0.

So element 1 in the list is at index 0 in the array

Element 2 in the list is at index 1 in the array

Element 3 in the list is at index 2 in the array

and so on..


no additional value to @JohannesSchaub's earlier answer
r
rokrfellr

How about this.. Somewhere in your class...

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

B
Bernhard Barker

If you modify your list, then use listIterator() and iterate from last index (that is size()-1 respectively). If you fail again, check your list structure.


U
Undo

All you need to do is use size() to get the last value of the Arraylist. For ex. if you ArrayList of integers, then to get last value you will have to

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

Remember, elements in an Arraylist can be accessed using index values. Therefore, ArrayLists are generally used to search items.


no additional value to @JohannesSchaub's earlier answer
c
closeab

arrays store their size in a local variable called 'length'. Given an array named "a" you could use the following to reference the last index without knowing the index value

a[a.length-1]

to assign a value of 5 to this last index you would use:

a[a.length-1]=5;


This is an ArrayList not an array.
P
Prasoon Mishra

To Get the last value of arraylist in JavaScript :

var yourlist = ["1","2","3"];
var lastvalue = yourlist[yourlist.length -1];

It gives the output as 3 .


T
Terran

Alternative using the Stream API:

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

Results in an Optional of the last element.


O
Ollie

In Kotlin, you can use the method last:

val lastItem = list.last()

This is java however
One of the ideas behind creating Kotlin was to cover the little uncomfortable sides of Java. So I think it makes sense to recommend considering Kotlin, at least for the parts of the application that do data analasys.