Java Collections - List

Implementations of List

Java provides several implementations of the List Interface - each tailored for a particular design requirement

ArrayList

This class provides the most commonly used List. Each ArrayList instance has a capacity. The capacity is the size of the array used to store the elements in the list. It is always at least as large as the list size. As elements are added to an ArrayList, its capacity grows automatically. The details of the growth policy are not specified beyond the fact that adding an element has constant time cost. An application can increase the capacity of an ArrayList instance before adding a large number of elements using the ensureCapacity operation. This may reduce the amount of incremental reallocation.
It is Not Thread Safe. There are no guarantees about how it will behave on concurrent access. Its fail-fast behavior is not guaranteed.

CopyOnWriteArrayList

As the name suggests, this class implements the List interface. Any write to this set triggers a new copy of the entire List. Although this sounds crazy, it is extremely useful when there is a heavy load of concurrent reads and very few writes onto a small List. In such a scenario, the concurrrent reads can continue without any block. You can be certain that its iterator will never through a ConcurrentModificationException. Ofcourse it is Thread Safe. But you should note that any mutative operations are expensive.

LinkedList

This class provides a doubly-linked list implementation of the List as well as the Deque interface. It implements all optional list operations, and permits all elements (including null). All of the operations perform as could be expected for a doubly-linked list. Operations that index into the list will traverse the list from the beginning or the end, whichever is closer to the specified index - hence its read performance is relatively slow. But, the linked list provide for quick inserts. It is Not Thread Safe. There are no guarantees about how it will behave on concurrent access. Its fail-fast behavior is not guaranteed.

Vector

The Vector class implements a growable array of objects. It tries to optimize storage management by maintaining a capacity and a capacityIncrement. The capacity is always at least as large as the vector size; it is usually larger because as components are added to the vector, the vector's storage increases in chunks the size of capacityIncrement. An application can increase the capacity of a vector before inserting a large number of components; this reduces the amount of incremental reallocation. It is Not Thread Safe. There are no guarantees about how it will behave on concurrent access. Its fail-fast behavior is not guaranteed. We all grew up learning the difference between the Vector and ArrayList is that Vector is thread safe. But the Java 8 documentation declares it is not so anymore. Moreover it discourages the use of Vector.

Stack

This class represents a last-in-first-out (LIFO) stack of objects. It extends the Vector, additionally providing methods that make it a stack. (peek(), push(E element), pop()). JDK documentation discourages the use of Stack saying "a more complete and consistent set of LIFO stack operations is provided by the Deque interface and its implementations, which should be used in preference to this class." It is Not Thread Safe. There are no guarantees about how it will behave on concurrent access. Its fail-fast behavior is not guaranteed.