11

I want to take out and remove first element from the List. I can see, I have two options:

First Approach:

LinkedList<String> servers = new LinkedList<String>();
....
String firstServerName = servers.removeFirst();

Second Approach

ArrayList<String> servers = new ArrayList<String>();
....
String firstServerName = servers.remove(0);

I have lot of elements in my list.

  • Is there any preference which one we should use?
  • And what is the difference between the above two? Are they technically same thing in terms of performance? What is the complexity involve here if we have lot of elements?

What is the most efficient way to do this.

Alexander Petrov
  • 9,204
  • 31
  • 70
user1950349
  • 4,738
  • 19
  • 67
  • 119
  • a) Define performance. There are many variables to measure for, such as time, efficiency, memory usage, etc. b) Write some testing code, using stopwatches (class, not physicals) and things of that nature to benchmark it and find out. – D. Ben Knoble Jun 04 '15 at 01:04
  • 1
    "What is the most efficient way to do this?" Depends on your scenario. See http://stackoverflow.com/questions/322715/when-to-use-linkedlist-over-arraylist – Shar1er80 Jun 04 '15 at 01:09

9 Answers9

6

If the comparison for "remove first" is between the ArrayList and the LinkedList classes, the LinkedList wins clearly.

Removing an element from a linked list costs O(1), while doing so for an array (array list) costs O(n).

PNS
  • 19,295
  • 32
  • 96
  • 143
6

You should use LinkedList.

Background:

In practical terms, LinkedList#removeFirst is more efficient since it's operating over a doubly-linked list and the removal of first element basically consist in only unlinking it from the head of the list and update the next element to be the first one (complexity O(1)):

private E unlinkFirst(Node<E> f) {
    // assert f == first && f != null;
    final E element = f.item;
    final Node<E> next = f.next;
    f.item = null;
    f.next = null; // help GC
    first = next;
    if (next == null)
        last = null;
    else
        next.prev = null;
    size--;
    modCount++;
    return element;
}

ArrayList#remove is operating over an internal array structure which requires moving all subsequent elements one position to the left by copying over the subarray (complexity O(n)):

public E remove(int index) {
    rangeCheck(index);

    modCount++;
    E oldValue = elementData(index);

    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work

    return oldValue;
}

Additional answer:

On the other hand, LinkedList#get operation requires traversing half of the entire list for retrieving an element at a specified index - in worst case scenario. ArrayList#get would directly access the element at the specified index since it's operating over an array.

My rule of thumbs for efficiency here would be:

  • Use LinkedList if you do a lot of add/remove in comparison with access operations (e.g.: get);
  • Use ArrayList if you do a lot of access operations in comparison with add/remove.
Ben-Hur Langoni Junior
  • 2,095
  • 1
  • 15
  • 14
5

Make sure you understand the difference between LinkedList and ArrayList. ArrayList is implemented using Array.

LinkedList takes constant time to remove an element. ArrayList might take linear time to remove the first element (to confirm I need to check the implementation, not java expert here).

Also I think LinkedList is more efficient in terms of space. Because ArrayList would not (and should not) re-size the array every time an element is removed, it takes up more space than needed.

Zlol
  • 94
  • 2
  • 2
    `ArrayList` in Java is not double-ended so it needs to shift everything when you remove the first item. `ArrayList` is more space efficient than `LinkedList` for large lists though since a LinkedList uses 3 references for each item (value, next and previous) whereas an `ArrayList` only needs one reference per item plus unused space. – Raniz Jun 04 '15 at 01:14
  • Don't forget the wrapper object takes up memory as well –  Jun 04 '15 at 01:19
  • @Raniz Thanks for adding the detail. Just to clarify, what I mean by "more efficient in terms of space" is that when an element is removed from linked-list, the list shrinks; in the case of ArrayList the ArrayList does not get resized after the deletion. Although trimToSize() helps. – Zlol Jun 04 '15 at 01:21
5

I think that what you need is an ArrayDeque (an unfairly overlooked class in java.util). Its removeFirst method performs in O(1) as for LinkedList, while it generally shows the better space and time characteristics of ArrayList. It’s implemented as a circular queue in an array.

You should very rarely use LinkedList. I did once in my 17 years as Java programmer and regretted in retrospect.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • You can also use `List.subList(...)`, see my answer https://stackoverflow.com/a/46211629/480894 – Roland Sep 14 '17 at 06:02
  • You can, @Roland. If both additions and removals go on, I cannot see how it will be practical, though. If the list is filled only once and after that only removed from, `subList()` should be fine. – Ole V.V. Sep 14 '17 at 06:40
4

List.subList​(int fromIndex, int toIndex)

Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive.

Good to use for ArrayList where removing the first element has complexity O(n).

final String firstServerName = servers.get(0);
servers = servers.subList(1, servers.size());
Roland
  • 7,525
  • 13
  • 61
  • 124
3

Using a linked list is by far faster.

LinkedList

It will just reference the nodes so the first one disappears. enter image description here

ArrayList

With an Array List it has to move all elements back one spot to keep the underlying array proper.

J Blaz
  • 783
  • 1
  • 6
  • 26
3

Removing the first element of an ArrayList is O(n). For the linked list is O(1), so I'll go with that.

Check the ArrayList documentation

The size, isEmpty, get, set, iterator, and listIterator operations run in constant time. The add operation runs in amortized constant time, that is, adding n elements requires O(n) time. All of the other operations run in linear time (roughly speaking). The constant factor is low compared to that for the LinkedList implementation.

This guys actually got the OpenJDK source link

Community
  • 1
  • 1
Cacho Santa
  • 6,846
  • 6
  • 41
  • 73
3

As others have rightly pointed out, LinkedList is faster than ArrayList for removal of the first element from anything other than a very short list.

However, to make your choice between them you need to consider the complete mix of operations. For example, if your workload does millions of indexed accesses to a hundred element list for each first element removal, ArrayList will be better overall.

Patricia Shanahan
  • 25,849
  • 4
  • 38
  • 75
2

Third Aproach.

It is exposed by the java.util.Queue interface. LinkedList is an implementation of this interface.

The Queue interface is exposing the E poll() method which effectively removes the head of the List (Queue).

In terms of performance the poll() method is comparable to removeFirst(). Actually it is using under the hood the removeFirst() method.

Alexander Petrov
  • 9,204
  • 31
  • 70