Java Collections Framework: ArrayList

Reading time: 15 minutes

Java ArrayList is one of the most widely used Collection class. java.util.ArrayList class implements java.util.List interface. Java ArrayList also implements RandomAccess, Cloneable and Serializable interfaces. Java ArrayList class extends AbstractList class that is the skeleton implementation of List interface.


Properties


Java ArrayList is the resizable array implementation of List interface, that means it starts with default size and grows automatically when more data is added into array list. Some important points about Java ArrayList are:

  • Java ArrayList is unsynchronized therefore its performance is better in single threaded environment.

  • Java ArrayList is not thread safe so care must be given when used in multithreaded environment.

  • Java ArrayList can contain duplicate values

  • Java ArrayList allows “null” value.

  • Objects in java ArrayList are added in order.

  • Java ArrayList default capacity is defined as 10. We can change the default capacity through the constructor or by calling ensureCapacity(int minCapacity) method.

  • Java ArrayList Iterator and ListIterator implementation is fail-fast. If the list structure is modified after creating the iterator in any other way except the iterator add or remove methods, it will throw ConcurrentModificationException

  • Java ArrayList provides random access

  • Java ArrayList supports Generics and is the recommended way


List list = new ArrayList(); //not the recommended way
List<String> list1 = new ArrayList<String>(); // recommended way

Java ArrayList Constructors


There are three constructor types in Java ArrayList class:

  • public ArrayList(): This ArrayList constructor will return an empty list with initial capacity of 10.

  • public ArrayList(int initialCapacity): This ArrayList constructor will return an empty list with initial capacity as specified by the initialCapacity argument. This constructor is useful when you know that your list will contain huge data and you want to save time of reallocation by providing a large value of initial capacity. If the initialCapacity argument is negative, it will throw IllegalArgumentException.

  • public ArrayList(Collection<? extends E> c): This ArrayList constructor will return a list containing the elements of the specified collection. It will throw famous NullPointerException if the specified collection argument is null.


// Java ArrayList default constructor
List<String> vowels = new ArrayList<String>();

//Java ArrayList constructor with initial capacity
List<String> dictionaryWordsList = new ArrayList<String>(50000);

vowels.add("A");
vowels.add("B");
vowels.add("C");
vowels.add("D");
vowels.add("E");

//Creating my list from different collection source
List<String> myList = new ArrayList<String>(vowels);

Java ArrayList Methods


Java ArrayList contains several methods such as:

  • public boolean add(E e): Appends the specified element to the end of the list.

  • public void add(int index, E element): Inserts the specified element at the specified position in the list. Shifts the element currently at that position and any subsequent elements to the right. If index is greater than list size or negative, it will throw IndexOutOfBoundsException.

  • public boolean addAll(Collection<? extends E> c): Appends all of the elements in the specified collection to the end of this list. This operation throws NullPointerException if the specified collection is null.

  • public boolean addAll(int index, Collection<? extends E> c): Inserts all of the elements in the specified collection into this list starting at the specified position. This method will throw IndexOutOfBoundsException if the index value is greater than list size or negative. This method also throws NullPointerException if specified collection is null.

  • public boolean contains(Object o): Returns true if this list contains the specified element.

  • public void clear(): Removes all of the elements from this list.

  • public void ensureCapacity(int minCapacity): Increases the capacity of this ArrayList instance, if necessary, to ensure that it can hold at least the number of elements specified by the minimum capacity argument.

  • public void forEach(Consumer<? super E> action): Performs the given action for each element of the Iterable until all elements have been processed or the action throws an exception.

  • public E get(int index): Returns the element at the specified position in this list.

  • public boolean isEmpty(): Returns true if this list contains no elements.

  • public int indexOf(Object o): Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element.

  • public Iterator<E> iterator(): Returns an iterator over the elements in this list in proper sequence. The returned iterator is fail-fast.

  • public int lastIndexOf(Object o): Returns the index of the last occurrence of the specified element in this list, or -1 if this list does not contain the element.

  • public ListIterator<E> listIterator(): Returns a list iterator over the elements in this list (in proper sequence). The returned list iterator is fail-fast.

  • public ListIterator<E> listIterator(int index): Returns a list iterator over the elements in this list (in proper sequence), starting at the specified position in the list. The specified index indicates the first element that would be returned by an initial call to next. An initial call to previous would return the element with the specified index minus one. This method throws IndexOutOfBoundsException if index value is greater than list size or negative.

  • public E remove(int index): Removes the element at the specified position in this list. Shifts any subsequent elements to the left (subtracts one from their indices).

  • public boolean remove(Object o): Removes the first occurrence of the specified element from this list, if it is present. If the list does not contain the element, it is unchanged.

  • public boolean removeAll(Collection<E> c): Removes from this list all of its elements that are contained in the specified collection.

  • public boolean retainAll(Collection<E> c): Retains only the elements in this list that are contained in the specified collection. In other words, removes from this list all of its elements that are not contained in the specified collection.

  • public boolean removeIf(Predicate<? super E> filter): Removes all of the elements of this collection that satisfy the given predicate.

  • public void replaceAll(UnaryOperator<E> operator): Replaces each element of this list with the result of applying the operator to that element.

  • public int size(): Returns the number of elements in this list.

  • public E set(int index, E element): Replaces the element at the specified position in this list with the specified element.

  • public List<E> subList(int fromIndex, int toIndex): Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive. The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa.

  • public Spliterator<E> spliterator(): Creates a late-binding and fail-fast Spliterator over the elements in this list.

  • public void sort(Comparator<? super E> c): Sorts this list according to the order induced by the specified Comparator.

  • public void trimToSize(): Trims the capacity of this ArrayList instance to be the list’s current size. An application can use this operation to minimize the storage of an ArrayList instance.

  • public Object[] toArray(): Returns an array containing all of the elements in this list in proper sequence (from first to last element). The returned array will be “safe” in that no references to it are maintained by this list. (In other words, this method must allocate a new array). The caller is thus free to modify the returned array.

  • public <T> T[] toArray(T[] a): Returns an array containing all of the elements in this list in proper sequence. If the list fits in the specified array, it is returned as is. Otherwise, a new array is allocated with the runtime type of the specified array and the size of this list.


Implementation



import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ArrayListExample 
{
  public static void main(String args[]) {
    List<String> data = new ArrayList<String>();
    //add example
    data.add("A");
    data.add("B");
    //let's insert C between A and B
    data.add(1,"C");
    System.out.println(data);
    List<String> data1 = new ArrayList<String>();
    data1.add("D");
    data1.add("E");
    //appending list elements to letters
    data.addAll(data1);
    System.out.println(data);
    //clear example to empty the list
    data1.clear();
    data1.add("1");
    //inserting list inside letters to get right sequence
    data.addAll(4, data1);
    System.out.println(data);
    //contains example
    System.out.println("data list contains 1 ? "+data.contains("1"));
    //ensureCapacity example, it's ArrayList method, so object should be defined like below.
    ArrayList<String> data2 = new ArrayList<>();
    data2.ensureCapacity(1000);
    //get example
    String out = data.get(3);
    System.out.println("Letter at 5th place: "+out);
    //tempList is empty?
    System.out.println("tempList is empty ? "+data2.isEmpty());
    //indexOf example
    System.out.println("First index of D = "+data.indexOf("D"));
    System.out.println("Last index of D = "+data.lastIndexOf("D"));
    //remove examples
    System.out.println(data);
    String removed = data.remove(3);
    System.out.println("After removing '"+removed+"' data contains "+data);
    //remove first occurrence of B
    boolean isRemoved = data.remove("B");
    System.out.println("H removed? "+isRemoved+". data contains "+data);
    System.out.println("data1 contains "+data1);
    //remove all matching elements between letters and list
    data.removeAll(data1);
    System.out.println(data);
    //retainAll example
    data1.clear();
    data1.add("A");
    data1.add("B");
    data.retainAll(data1);
    System.out.println("data elements after retainAll operation: "+data);
    //size example
    System.out.println("data ArrayList size = "+data.size());
    //set example
    data.set(2, "D");
    System.out.println(data);
    //toArray example
    String[] strArray = new String[data.size()];
    strArray = data.toArray(strArray);
    System.out.println(Arrays.toString(strArray));
  }
}

Sorting an ArrayList


Following example demonstrates sorting an ArrayList:


import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
public class ArrayListSorting {
	public static void main(String[] args) {
		List<Integer> data = new ArrayList<>();
		Random random = new Random();
		for (int i = 0; i < 5; ++i) 
			data.add(random.nextInt(1000));
		System.out.println("Original List: "+data);
		// sort the list
		MyComparator c = new ArrayListSorting(). new MyComparator();
		data.sort(c);
		System.out.println("Sorted in Increasing Order: "+data);
		// sort in reverse order
		data.sort((d1,d2) -> {return (d2-d1);});
		System.out.println("Sorted in Decreasing Order: "+data);
	}
	class MyComparator implements Comparator<Integer>{
		@Override
		public int compare(Integer d1, Integer d2) {
			return (d1 - d2);
		}	
	}
}

Thread Safety in ArrayList


Java ArrayList is not thread-safe by default. Use the following code to get thread-safe ArrayList.


List<Integer> synchronizedList = Collections.synchronizedList(ints);

You can also use CopyOnWriteArrayList concurrent collection class in this case.