Complete Reference of ArrayList Collection in Java with Examples


ArrayList Collection in Java

This article provides an in-depth overview of the ArrayList<E> collection in Java, its benefits, and how to use it in Java with practical examples.

Readability: ⭐ ⭐ ⭐ (Intermediate)
Time to read: 20 minutes


Table of Contents

  1. Prerequisite
  2. Overview
  3. Hierarchy Diagram
  4. Class Diagram
  5. Defining ArrayList<E>
  6. Creating Objects of ArrayList using its Constructors
  7. Add, Remove, and Modify elements in ArrayList
  8. Differernce between set() and add() method
  9. Get elements of a ArrayList<E>
  10. Remove all elements
  11. clone() method
  12. forEach() method
  13. ensureCapacity() method
  14. equals() and hashCode() methods of ArrayList
  15. Ways to Iterate over ArrayList
  16. How to get the size of ArrayList
  17. How to check if ArrayList is empty
  18. List of Exceptions related to ArrayList
  19. OutOfMemory error


1. Prerequisite

prerequisite

    To understand the Java Collections Framework, you should have a good understanding of the following concepts:

    • Object-oriented programming (OOP): Java is an object-oriented programming language, which means that it is designed to model real-world objects and their interactions.
    • Interfaces: Interfaces define a set of methods that a class must implement, allowing for polymorphism and providing a way to define common behavior across multiple classes.
    • Inheritance: Inheritance allows a subclass to inherit properties and methods from its parent class, providing a way to reuse code and create class hierarchies.
    • Generics: Generics provide a way to specify the type of objects that a collection can hold, allowing for type-safe collections and reducing the need for explicit casting.
    • Exceptions: Exceptions provide a way to handle runtime errors and unexpected conditions in a program, allowing for more robust and reliable code.
    • Data structures: Data structures such as lists, sets, and maps provide a way to store and organize collections of data, allowing for more efficient access and manipulation of the data.


2. Overview

    ArrayList<E> is a class in the Java Collections Framework that implements the List<E> interface. It provides a resizable array that can hold objects of any type. You can find ArrayList<E> is part of the java.util package in Java.

    In general, a list is an ordered collection of elements. Elements can be added or removed from the list, and they are stored in a specific order based on their index. The List<E> interface provides a set of methods to access and manipulate the elements in the List.

    Besides ArrayList<E>, other concrete classes that implement the List<E> interface in the Java Collections Framework include:

    1. LinkedList<E>: a linked list implementation of the List<E> interface.
    2. Vector<E>: a synchronized implementation of the List<E> interface that is similar to ArrayList<E>.
    3. Stack<E>: a subclass of Vector<E> that implements a stack data structure.

    Each of these concrete classes has its strengths and weaknesses, depending on the specific use case.

    ArrayList<E> is often the preferred choice because of its fast random access times and efficient memory usage. It is a very versatile data structure that can be used in a wide range of applications, from small programs to large-scale enterprise systems.



3. Hierarchy Diagram

    ArrayList Class Hierarchy

    At the top of the hierarchy we have the Iterable<E> interface. It defines a single method, iterator(), that returns an iterator that is used to iterate over the elements of an ArrayList.

    The Iterable<E> interface extends the Collection<E> interface, which in turn extends the AbstractCollection<E> class.

    The AbstractCollection<E> class provides a partial implementation of the Collection<E> interface, defining some of its methods and leaving others to be implemented by subclasses.

    Below the AbstractCollection<E> class in the hierarchy are several concrete classes that implement the List<E> interface. One such class is the AbstractList<E> class, which provides a partial implementation of the List<E> interface and also extends the AbstractCollection<E> class.

    The AbstractList<E> class is then extended by the ArrayList<E> class, which provides a resizable array implementation of the List<E> interface. ArrayList<E> also implements the RandomAccess interface, which indicates that the list can be accessed efficiently using random index access.

    ArrayList<E> also implements the Cloneable and Serializable interfaces, which allow it to be cloned and serialized, respectively.

    In short, the hierarchy of ArrayList is: Iterable -> Collection -> AbstractCollection -> AbstractList -> ArrayList



4. Class Diagrarm

    +------------------------------------------------------------------------------+
    |                                ArrayList<E>                                  |
    +------------------------------------------------------------------------------+
    | - elementData: Object[]                                                      |
    | - size: int                                                                  |
    +------------------------------------------------------------------------------+
    | + ArrayList()                                                                |
    | + ArrayList(Collection<? extends E>                                          |
    | + ArrayList(int)                                                             |
    | + add(E): boolean                                                            |
    | + add(int, E): void                                                          |
    | + addAll(Collection<? extends E>): boolean                                   |
    | + addAll(int, Collection<? extends E>): boolean                              |
    | + clear(): void                                                              |
    | + clone(): Object                                                            |
    | + contains(Object): boolean                                                  |
    | + ensureCapacity(int): void                                                  |
    | + get(int): E                                                                |
    | + indexOf(Object): int                                                       |
    | + isEmpty(): boolean                                                         |
    | + lastIndexOf(Object): int                                                   |
    | + remove(Object): boolean                                                    |
    | + remove(int): E                                                             |
    | + removeAll(Collection<?>): boolean                                          |
    | + removeIf(Predicate<? super E>): boolean                                    |
    | + retainAll(Collection<?>): boolean                                          |
    | + set(int, E): E                                                             |
    | + size(): int                                                                |
    | + sort(Comparator<? super E>): void                                          |
    | + spliterator(): Spliterator<E>                                              |
    | + subList(int, int): List<E>                                                 |
    | + toArray(): Object[]                                                        |
    | + toArray(T[]): T[]                                                          |
    +------------------------------------------------------------------------------+
    

    This above class diagram represents the hierarchy of the ArrayList class. The ArrayList class is a concrete implementation of the List interface, which is itself a sub-interface of the Collection interface.

    The ArrayList class contains two fields:

    1. elementData: It is an array that holds the elements of the list.
    2. size: It is used to provide the exact number of elements in the list.

    The ArrayList class provides a number of methods for manipulating the list, such as add(), remove(), clear(), get(), set(), and size(). It also provides methods for manipulating multiple elements at once, such as addAll(), removeAll(), retainAll(), and subList().

    In addition, the ArrayList class implements the RandomAccess marker interface, which indicates that it provides fast random access to its elements. It also implements the Cloneable and Serializable interfaces, which allow for the cloning and serialization of ArrayList instances, respectively.

    Finally, the ArrayList class extends the AbstractList class, which is an abstract implementation of the List interface. The AbstractList class in turn extends the AbstractCollection class, which is an abstract implementation of the Collection interface.

    The AbstractList and AbstractCollection classes provide some common functionality that can be shared among different list and collection implementations.



5. Defining ArrayList<E>: Resizable Array

    In Java ArrayList is a class that represents a resizable array.

    What are resizable array?

    A resizable array, also known as a dynamic array, growable array, dynamic table, or mutable array, is an array-like data structure that allows for the size of the array to be changed during runtime. Unlike traditional arrays, which have a fixed size that is specified at the time of creation, a resizable array can be expanded or shrunk as required.

    In a resizable array, the underlying array that holds the elements is dynamically resized as elements are added or removed. When more space is needed to accommodate additional elements, the array is resized to a larger size. Conversely, when elements are removed and the array is no longer fully utilized, the array can be resized to a smaller size to conserve memory.

    Resizing an array involves creating a new array with the desired size and copying the existing elements from the old array to the new array. This can be an expensive operation in terms of time and memory usage, so resizable arrays typically implement various strategies to minimize the frequency of resizing and the associated overhead.

    Example of how the ArrayList grows?

    Let's say we have an ArrayList of size 3 and we want to add a new element to it. Since the ArrayList is already at its maximum capacity, it needs to grow in size to accommodate the new element.

    An ArrayList of size 3 that already has 3 elements

    ArrayList Size: [ x , x , x ]
    Elements: [1, 2, 3]

    Now we want to add a new element, "4", to the ArrayList. However, since the current size of the ArrayList is already at its maximum capacity, it needs to grow in size.

    When the ArrayList needs to grow, it creates a new, larger array to hold the elements. In this case, let's say the new array has a capacity of 6.

    New Larger ArrayList Created: [ x , x , x , x , x, x]

    The elements from the original ArrayList are then copied over to the new array. In this case, the original elements are copied over to the first four positions of the new array.

    New Larger ArrayList Created: [ 1 , 2 , 3 , x , x, x]

    The new element, "4", is then added to the next available position in the array, which is position 3.

    New Larger ArrayList Created: [1 , 2 , 3 , 4 , x, x]

    Finally we have an ArrayList now has a size of 4 and a capacity of 5.



6. Creating Objects of ArrayList using its Constructors

    There are 3 constructors in the ArrayList class,

    1. public ArrayList()
       Constructs an empty list with an initial capacity of 10.
    
    2. public ArrayList(int initialCapacity)
       Constructs an empty list with the param initialCapacity.
    
    3. public ArrayList(Collection<? extends E> c)
       Constructs a list containing the elements of the specified collection

    1. ArrayList()

    This is the default constructor of the ArrayList class, which creates an empty ArrayList with an initial capacity of 10. You can use this constructor when you don't know the size of the ArrayList in advance, but you need to add elements to it later.

    Example:
    ArrayList<String> myList = new ArrayList<>();

    2. ArrayList(int initialCapacity)

    This constructor creates an empty ArrayList with the specified initial capacity using the initialCapacity.

    The initial capacity is the size of the internal array that stores the elements. You can use this constructor when you know the size of the ArrayList in advance and want to optimize its performance by avoiding frequent resizing of the internal array.

    Example:
    ArrayList<String> myList = new ArrayList<>(2000);

    The above will create an ArrayList with an initial capacity of 2000.


    3. ArrayList(Collection<? extends E> c)

    Using this constructor you can create an ArrayList that contains the elements of the specified collection, in the order, they are returned by the collection's iterator. You can use this constructor when you want to create a new ArrayList that is a copy of an existing collection.

    Example:
    ArrayList<String> oldArrayList = new ArrayList<>();
    oldArrayList.add("USA");
    oldArrayList.add("Canada");
    oldArrayList.add("UK");
    
    ArrayList<String> newArrayList = new ArrayList<>(oldArrayList);

    As you may see we created a new ArrayList that contains the same elements as the oldArrayList object.



7. Add, Remove, and Modify elements in ArrayList

Adding Elements:

We can make use of the below 4 methods to add elements to an ArrayList based on our use case.

  1. public boolean add(E e)
  2. public void add(int index, E element)
  3. public boolean addAll(Collection c)
  4. public boolean addAll(int index, Collection<? extends E> c)

1. public boolean add(E e)

    To add elements to an ArrayList, you can use the add() method. Note that the type of the element is based on what time you define while creating the ArrayList<E> object.

    Example:
    ArrayList<String> namesList = new ArrayList<>();
    
    //Adding Elements to ArrayList
    namesList.add("Sam");
    namesList.add("Dean");
    namesList.add("Castiel");
    namesList.add("John");
    
    //Print the elements of ArrayList
    System.out.println(namesList);

    [Sam, Dean, Castiel, John]

    As you add more elements to the ArrayList, they are appended at the end of the List.

    The add(E e) method returns a boolean value.

    ArrayList<Integer> evenNumbers = new ArrayList<>();
    
    boolean bool = evenNumbers(4);
    System.out.println(bool);

    true


2. public void add(int index, E element)

    If you want to add an element at a specific index of the ArrayList make use of the add() method with two parameters,

    1. int index: The index at which the specified element is to be inserted.
    2. E element – element to be inserted.

    Example:
    ArrayList<String> namesList = new ArrayList<>();
    
    //Adding Elements to ArrayList
    namesList.add("Sam");
    namesList.add("Dean");
    namesList.add("Castiel");
    namesList.add("John");
    
    System.out.println(namesList);
    
    //Adding element at specific index
    namesList.add(2,"Mary");
    
    System.out.println(namesList);

    [Sam, Dean, Castiel, John]
    [Sam, Dean, Mary, Castiel, John]

    We have added four elements to the namesList ArrayList using the add() method: "Sam", "Dean", "Castiel", and "John". These elements are added to the end of the ArrayList, in the order in which they are added.

    Next, we add an element to the namesList ArrayList at a specific index using the add(int index, E element) method. In this case, we're adding the element "Mary" at index 2 (remember index starts with 0), which pushes the existing element "Castiel" and all subsequent elements to higher indexes.


3. public boolean addAll(Collection<? extends E> c)

    To append all of the elements of another collection to the end of an existing ArrayList you can make use of the addAll() method.

    ArrayList<String> namesList1 = new ArrayList<>();
    namesList1.add("Sam");
    namesList1.add("Dean");
    
    ArrayList<String> namesList2 = new ArrayList<>();
    namesList2.add("Castiel");
    namesList2.add("Mary");
    
    //Add all elements of namesList2 to namesList1
    namesList1.addAll(namesList2);
    
    System.out.println(namesList1);

    Output: [Sam, Dean, Castiel, Mary]

    If the collection to be added is empty, the method will return a boolean false.

    ArrayList<String> namesList1 = new ArrayList<>();
    namesList1.add("Sam");
    namesList1.add("Dean");
    
    ArrayList<String> namesList2 = new ArrayList<>();
    boolean b = namesList1.addAll(namesList2);
    
    System.out.println(b); //false

4. public boolean addAll(int index, Collection<? extends E> c)

    If you want to add a collection at a specific index, make use of the addAll(int index, Collection<? extends E> c) method.

    ArrayList<String> namesList = new ArrayList<>();
    namesList.add("Sam");
    namesList.add("Dean");
    
    ArrayList<String> newNames = new ArrayList<>();
    newNames.add("Castiel");
    newNames.add("Mary");
    
    // add all elements of newNames at index 1 in namesList
    namesList.addAll(1, newNames);
    
    System.out.println(namesList);

    Output: [Sam, Castiel, Mary, Dean]


Remove Elements:

To remove elements from an ArrayList, you can make use of the below methods.

Note that removing elements from an ArrayList is expensive to process because it requires shifting all elements after the removed element one position to the left to fill the gap. This can be particularly expensive if the ArrayList is large and contains many elements. When an element is removed from the middle of the ArrayList, all the subsequent elements have to be shifted to the left to fill the gap, and this requires copying all the elements to new positions in the array. If the ArrayList is very large, this can take a long time and use a lot of memory.

Therefore, it is often a good idea to use other data structures, such as LinkedList or HashSet, if frequent removal of elements is required.

  1. public E remove(int index)
  2. public boolean remove(Object o)
  3. public boolean removeAll(Collection<?> c)
  4. public boolean removeIf(Predicate<? super E> filter)
  5. boolean removeIf(Predicate<? super E> filter, int i, final int end)
  6. protected void removeRange(int fromIndex, int toIndex)

1. public E remove(int index)

    Removes the element at the specified index in the ArrayList and returns it. The indices of subsequent elements are shifted left to fill the gap.

    ArrayList<String> namesList = new ArrayList<>();
    namesList.add("Sam");
    namesList.add("Dean");
    namesList.add("Castiel");
    
    String removedName = namesList.remove(1); // removes "Dean" at index 1
    
    System.out.println(namesList); // Output: [Sam, Castiel]
    System.out.println(removedName); // Output: Dean

2. public boolean remove(Object o)

    Removes the first occurrence of the specified element from the ArrayList, if it is present.

    ArrayList<String> namesList = new ArrayList<>();
    namesList.add("Sam");
    namesList.add("Dean");
    namesList.add("Castiel");
    
    boolean removed = namesList.remove("Dean"); // removes "Dean"
    
    System.out.println(namesList); // Output: [Sam, Castiel]
    System.out.println(removed); // Output: true
    
    removed = namesList.remove("Bobby"); // returns false since "Bobby" is not in the ArrayList
    
    System.out.println(removed); // Output: false

    As you can see when we use remove("Dean") we get a boolean true as the element is present in the list, whereas false for remove("Bobby") as it is not.

3. public boolean removeAll(Collection<?> c)

    Removes all elements from the ArrayList that are also contained in the specified collection.

    ArrayList<String> namesList = new ArrayList<>();
    namesList.add("Sam");
    namesList.add("Dean");
    namesList.add("Castiel");
    
    ArrayList<String> toRemove = new ArrayList<>();
    toRemove.add("Dean");
    toRemove.add("Bobby");
    
    boolean removed = namesList.removeAll(toRemove); // removes "Dean"
    
    System.out.println(namesList); // Output: [Sam, Castiel]
    System.out.println(removed); // Output: true

    Note: As you would have noticed that the list to remove contained "Bobby" and "Dean" of which only "Dean" is present in the namesList.

4. public boolean removeIf(Predicate<? super E> filter)

    Removes all elements from the ArrayList that match the given predicate.

    ArrayList<String> namesList = new ArrayList<>();
    namesList.add("Sam");
    namesList.add("Dean");
    namesList.add("Castiel");
    
    boolean removed = namesList.removeIf(name -> name.startsWith("C")); // removes "Castiel"
    
    System.out.println(namesList); // Output: [Sam, Dean]
    System.out.println(removed); // Output: true

    This is a relatively new method introduced in the ArrayList class in Java 8. In the above example, we make use of the removeIf method to remove all elements that start with C.

5. boolean removeIf(Predicate<? super E> filter, int i, final int end)

    Removes all elements from the ArrayList that match the given predicate in the given range of indices.

    ArrayList<String> namesList = new ArrayList<>();
    namesList.add("Sam");
    namesList.add("Dean");
    namesList.add("Castiel");
    namesList.add("Bobby");
    namesList.add("Charlie");
    
    boolean removed = namesList.removeIf((name, index) -> index > 1 && index < 4); // removes "Castiel" and "Bobby"
    
    System.out.println(namesList); 
    System.out.println(removed);

    [Sam, Dean, Charlie]
    true

6. protected void removeRange(int fromIndex, int toIndex)

    Removes all elements from the ArrayList in the specified range of indices.

    ArrayList<String> namesList = new ArrayList<>();
    namesList.add("Sam");
    namesList.add("Dean");
    namesList.add("Castiel");
    namesList.add("Bobby");
    namesList.add("Charlie");
    
    namesList.removeRange(1, 4); // removes "Dean", "Castiel", and "Bobby"
    
    System.out.println(namesList);

    [Sam, Charlie]


Modify Elements

You can modify an element in an ArrayList by using the set() and replace() methods. The set method replaces the element at the specified index with the new element provided. The new element should be of the same type as the ArrayList, or a subtype of the ArrayList type.

The replace method is used to replace all occurrences of a particular element with another element in the ArrayList.

Note that modifying an element in an ArrayList is a constant time operation, which means that it's very fast and efficient.

  1. public E set(int index, E element)
  2. public void replaceAll(UnaryOperator<E> operator)

1. public E set(int index, E element)

    ArrayList<String> names = new ArrayList<>();
    names.add("Alice");
    names.add("Bob");
    names.add("Charlie");
    
    // Set the element at index 1 to "Dave"
    String previous = names.set(1, "Dave");
    
    System.out.println("Previous element: " + previous);
    System.out.println("New ArrayList: " + names);

    Previous element: Bob
    New ArrayList: [Alice, Dave, Charlie]

2. public void replaceAll(UnaryOperator operator)

    This method was added in Java 8 and is used to replace each element in the ArrayList with the result of applying the given UnaryOperator to that element.

    ArrayList<Integer> numbers = new ArrayList<>();
    numbers.add(1);
    numbers.add(2);
    numbers.add(3);
    numbers.add(4);
    numbers.add(5);
    
    // Square each element in the ArrayList
    numbers.replaceAll(x -> x * x);
    
    System.out.println(numbers);

    [1, 4, 9, 16, 25]



8. Differernce between set() and add() method

It is very important to know the difference between the set and the add method, lets do that using a table.

    add(int index, E element) set(int index, E element)
    Inserts the specified element at the specified position in the list, shifting the elements currently at that position (if any) and any subsequent elements to the right. Replaces the element at the specified position in the list with the specified element.
    Parameters:
    - index: the index at which to insert the element
    - element: the element to insert into the list
    Parameters:
    - index: the index of the element to replace
    - element: the new value to set at the specified index
    Return type: void Return type: E - the element previously at the specified index


9. Get elements of a ArrayList<E>

    As ArrayList is index based, you can get the elements from it using the get(int index) method.

    But what if do not know the index of an element and want to know if it is present in the list or not, in such case, you can make use of indexOf(Object o) which will return the index number of the first occurrence of an element. If the element is not present you will get -1.

    Similarly, you can make use of lastIndexOf(Object o) to get the index of the last occurrence of the element.

    Let's take a look at all the methods you can make use of to get elements from an ArrayList.

    1. E get(int index): Returns the element at the specified position in the list.
    2. Object[] toArray(): Returns an array containing all of the elements in this list in proper sequence (from first to last element).
    3. <T> T[] toArray(T[] a): Returns an array containing all of the elements in this list in proper sequence (from first to last element); the runtime type of the returned array is that of the specified array.
    4. List<E> subList(int fromIndex, int toIndex): Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive.
    5. 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.
    6. 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.
    Examples:
    ArrayList<String> namesList = new ArrayList<>();
    namesList.add("Sam");
    namesList.add("Dean");
    namesList.add("Castiel");
    namesList.add("John");
    
    // Retrieve an element at a specific index
    String name = namesList.get(2); // Returns "Castiel"
    
    // Convert the ArrayList to an array
    Object[] namesArray = namesList.toArray(); 
    
    // Retrieve a sub-list of elements
    List<String> subList = namesList.subList(1, 3); // Returns ["Dean", "Castiel"]
    
    // Get the index of an element
    int index = namesList.indexOf("Dean"); // Returns 1
    
    // Get the last index of an element
    int lastIndex = namesList.lastIndexOf("Dean"); // Returns 1
    

    It public boolean contains(Object o) would be a helpful method to first check if an element is present in the ArrayList or not before performing any further operations based on it.



10. Remove all elements

    We have taken a look at the removeAll(Collection&ly;?> c) method that can be used to remove elements from a collection. But to flush all elements from a ArrayList and make it empty, make use of the clear() method.

    Example:

    ArrayList<String> namesList = new ArrayList<>();
    namesList.add("Sam");
    namesList.add("Dean");
    namesList.add("Castiel");
    namesList.add("John");
    
    // Clear all elements from the ArrayList
    namesList.clear();

    Note: The return type of clear() method is void.



11. clone() method

    The clone() method in ArrayList creates a shallow copy of the ArrayList. That is, it creates a new ArrayList object with the same elements and the same order as the original ArrayList. However, the elements themselves are not cloned - the new ArrayList contains references to the same elements as the original ArrayList.

    This means that changes made to an element in the new ArrayList will be reflected in the original ArrayList, and vice versa.

    Let's see this by an example:

    ArrayList<String> originalList = new ArrayList<>();
    originalList.add("Sam");
    originalList.add("Dean");
    originalList.add("Castiel");
    
    //Cloning the object originalList as clonedList
    ArrayList<String> clonedList = (ArrayList<String>) originalList.clone();
    
    System.out.println(clonedList); // Output [Sam, Dean, Castiel]
    
    // Modify an element in the cloned list
    clonedList.set(0, "Bobby");
    System.out.println(clonedList); // Output [Bobby, Dean, Castiel]
    System.out.println(originalList); // Output [Sam, Dean, Castiel]
    
    // Modify an element in the original list
    originalList.set(2, "Crowley");
    System.out.println(clonedList); // Output [Sam, Dean, Crowley]
    System.out.println(originalList); // Output [Sam, Dean, Crowley]


12. forEach Method

    The forEach() method in ArrayList is used to act on each element of the list that was introduced to the ArrayList class in Java 8. It takes a Consumer functional interface as an argument that defines the action to be performed on each element.

    ArrayList<String> namesList = new ArrayList<>();
    namesList.add("Sam");
    namesList.add("Dean");
    namesList.add("Castiel");
    namesList.add("John");
    
    //Using forEach to print each element in the list
    namesList.forEach(name -> System.out.println("Hello "+ name));

    Hello Sam
    Hello Dean
    Hello Castiel
    Hello John



13. ensureCapacity() method

    ensureCapacity(int minCapacity) is a method in the ArrayList class in Java that ensures that the underlying array of the ArrayList has at least the given minimum capacity. If the current capacity of the ArrayList is less than the specified minimum capacity, then a new array is allocated with a larger capacity.

    Example:
    import java.util.ArrayList;
    
    public class ArrayListExample {
        public static void main(String[] args) {
            ArrayList<Integer> numbers = new ArrayList<Integer>();
    
            numbers.add(1);
            numbers.add(2);
            numbers.add(3);
            
            numbers.ensureCapacity(35);
    
            for (int i = 0; i < 30; i++) {
                numbers.add(i + 30);
            }
    
            System.out.println(numbers);
        }
    }

    We have an ArrayList named numbers, which stores three integers 1,2, and 3.

    The ensureCapacity() method is called with an argument of 35, which sets the initial capacity of the ArrayList to 35. This means that the ArrayList can hold up to 35 elements without needing to be resized, which can improve performance if you know that the list will be large.

    The for loop then adds 30 more integers to the list using the add() method. Since the initial capacity was set to 35, the ArrayList does not need to be resized during this loop, which can improve performance compared to resizing the list multiple times.



14. equals() and hashCode() methods

    The ArrayList class overrides equals() and hashCode() of the Object class to provide custom implementations for its objects.


    The equals() method compares two ArrayList objects for equality based on the elements they contain. The method returns true if the two lists have the same size and contain the same elements in the same order; otherwise, it returns false.

    Equals Example:
    ArrayList<String> list1 = new ArrayList<String>();
    list1.add("Sam");
    list1.add("Bobby");
    list1.add("Dean");
    
    ArrayList<String> list2 = new ArrayList<String>();
    list2.add("Sam");
    list2.add("Bobby");
    list2.add("Dean");
    
    System.out.println(list1.equals(list2));

    true


    The hashCode() method returns a unique hash code value for each ArrayList object. It uses the elements contained in the list to generate the hash code value.

    HashCode Example:
    ArrayList<String> list1 = new ArrayList<String>();
    list1.add("Sam");
    list1.add("Mary");
    list1.add("Bobby");
    
    ArrayList<String> list2 = new ArrayList<String>();
    list2.add("Sam");
    list2.add("Mary");
    list2.add("Bobby");
    
    System.out.println(list1.hashCode()); 
    System.out.println(list2.hashCode());
    Output:

    -2139403102
    -2139403102



15. Ways to Iterate over ArrayList

    ArrayList provides four different types of iterators:

    1. Iterator: This interface provides basic iteration functionality, such as the ability to iterate over elements in the collection and remove elements while iterating.

    2. ListIterator: This interface extends Iterator and provides additional functionality for iterating over lists, such as the ability to iterate in both forward and backward directions, and to modify elements while iterating.

    3. Spliterator: This interface is used to traverse and partition elements of a collection in a parallel processing environment.

    4. Enumeration: This interface is the legacy version of Iterator, and is used to iterate over elements in older Java collections such as Vector and Hashtable. It is not recommended to use Enumeration with ArrayList, as it can cause compatibility issues.

    Example ArrayList
    ArrayList<String> namesList = new ArrayList<>();
    namesList.add("Dean");
    namesList.add("Sam");
    namesList.add("Bobby");

    1. Iterator Example:
    Iterator<String> iterator = namesList.iterator();
    
    while(iterator.hasNext()) {
        System.out.println(iterator.next());
    }

    2. ListIterator Example:
    ListIterator<String> listIterator = namesList.listIterator();
    
    while(listIterator.hasNext()) {
        System.out.println(listIterator.next());
    }
    
    System.out.println();
    
    while(listIterator.hasPrevious()) {
        System.out.println(listIterator.previous());
    }

    3. forEach and Lambda example:
    namesList.forEach(name -> System.out.println(name));

    4. for-each loop example:
    for(String name : namesList) {
        System.out.println(name);
    }


16. How to get the size of ArrayList

    To get the size of an ArrayList, you can use the size() method which returns the number of elements in the list as an int value.

    Example:
    ArrayList<String> namesList = new ArrayList<>();
    namesList.add("Sam");
    namesList.add("Dean");
    namesList.add("Castiel");
    
    int size = namesList.size();
    System.out.println("The size of the namesList is: " + size);

    The size of the namesList is 3



17. How to check if ArrayList is empty

    To know if an ArrayList is empty or not, make use of the isEmpty() method. This method returns a boolean true if the ArrayList is empty.

    Example:
    ArrayList<String> list1 = new ArrayList<String>();
    System.out.println(list1.isEmpty());

    true



18. List of Exceptions related to ArrayList

Many exceptions come up when you try to work with ArrayList, we will try to look at most of them here.

1. IndexOutOfBoundsException

    IndexOutOfBoundsException exception is thrown when an index is out of range, either lower than zero or greater than the size of the ArrayList.

    Example:
    1. import java.util.ArrayList;
    2. 
    3. public class Example {
    4. 
    5.    public static void main(String[] args) {
    6.        ArrayList<String> names = new ArrayList<>();
    7.        names.add("Sam");
    8.        names.add("Dean");
    9.        System.out.println(names.get(5));
    10.    }
    11.    
    12. }
    Error Stack:
    Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 5 out of bounds for length 2
    	at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:100)
    	at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:106)
    	at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:302)
    	at java.base/java.util.Objects.checkIndex(Objects.java:385)
    	at java.base/java.util.ArrayList.get(ArrayList.java:427)
    	at Example.main(Example.java:9)

    As you may see on line number 9, we are trying to access the element at index 2 (element 3) whereas the size of the ArrayList is 2.

2. NullPointerException

    NullPointerException can occur in many ways, one of them is when you access an element of an ArrayList and try to perform any operation on it.

    Example:
    ArrayList<String> names = new ArrayList<>();
    names.add("Sam");
    names.add("Dean");
    names.add(null);
    
    System.out.println(names.get(2).length());
    Error Stack:
    Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" 
        because the return value of "java.util.ArrayList.get(int)" is null
    	at Example.main(Example.java:10)

3. ConcurrentModificationException

    This exception is thrown when an ArrayList is modified while it is being iterated.

    ArrayList<String> names = new ArrayList<>();
    names.add("Sam");
    names.add("Dean");
    
    for (String name : names) {
        names.remove(name);
    }
    
    Exception:
    Exception in thread "main" java.util.ConcurrentModificationException
    	at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1013)
    	at java.base/java.util.ArrayList$Itr.next(ArrayList.java:967)
    	at Example.main(Example.java:13)

    To avoid this exception, you can use an iterator to remove elements from the ArrayList while iterating over it.

    ArrayList<String> names = new ArrayList<>();
    names.add("Sam");
    names.add("Dean");
    
    Iterator<String> iterator = names.iterator();
    while (iterator.hasNext()) {
        String name = iterator.next();
        iterator.remove();
    }

4. UnsupportedOperationException

    This exception is thrown when an operation is not supported by the ArrayList implementation.

    ArrayList<String> names = new ArrayList<>();
    names.add("Sam");
    names.add("Dean");
    
    List<String> unmodifiableList = Collections.unmodifiableList(names);
    unmodifiableList.remove(0);
    Exception in thread "main" java.lang.UnsupportedOperationException
    	at java.base/java.util.Collections$UnmodifiableList.remove(Collections.java:1355)
    	at Example.main(Example.java:13)

    When we try to remove an element from the unmodifiable list using the remove method, it throws an UnsupportedOperationException since the unmodifiableList view does not allow modification of the underlying names list.

5. ClassCastException

    This exception is thrown when an attempt is made to cast an object to a type that it is not.

    ArrayList<Object> names = new ArrayList<>();
    names.add("Sam");
    names.add("Dean");
    
    Integer age = (Integer) names.get(0);
    Error Stack:
    Exception in thread "main" java.lang.ClassCastException: class java.lang.String
     cannot be cast to class java.lang.Integer (java.lang.String and java.lang.Integer 
     are in module java.base of loader 'bootstrap')
    	at Example.main(Example.java:12)


19. OutOfMemory error with ArrayList

    If the size of an ArrayList exceeds the maximum size of an integer, which is Integer.MAX_VALUE, it will throw an OutOfMemoryError. This error occurs when the JVM cannot allocate enough memory for the object.

    import java.util.ArrayList;
    
    public class Example {
        public static void main(String[] args) {
            ArrayList<Integer> numbers = new ArrayList<Integer>();
    
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                numbers.add(i);
            }
        }
    }
    Error:
    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    	at java.base/java.util.Arrays.copyOf(Arrays.java:3512)
    	at java.base/java.util.Arrays.copyOf(Arrays.java:3481)
    	at java.base/java.util.ArrayList.grow(ArrayList.java:237)
    	at java.base/java.util.ArrayList.grow(ArrayList.java:244)
    	at java.base/java.util.ArrayList.add(ArrayList.java:454)
    	at java.base/java.util.ArrayList.add(ArrayList.java:467)
    	at Example.main(Example.java:8)

    The above is a simple example to demonstrate how a OutOfMemoryError may occur while working with ArrayList.



References

-

Facing issues? Have Questions? Post them here! I am happy to answer!


Author Info:

Rakesh (He/Him) is a seasoned developer with over 10 years of experience in web and app development, and a deep knowledge of operating systems. Author of insightful How-To articles for Code2care.

Follow him on: X

You can also reach out to him via e-mail: rakesh@code2care.org

Copyright © Code2care 2024 | Privacy Policy | About Us | Contact Us | Sitemap