00:00

ArrayList in Java – Complete Guide with Examples

Last updated: 19 min read

ArrayList is the most used collection class in Java. It stores elements in order, like an array, but it grows and shrinks automatically as you add and remove elements. It lives in the java.util package, implements the List interface and has been part of the Collections Framework since JDK 1.2.

In this tutorial you will learn how to create an ArrayList, add, read, update and remove elements, loop through it, sort it, convert it to and from arrays, and understand how it works inside. Every example is a complete program you can copy and run.

1. What Is an ArrayList?

An ArrayList is a resizable array. A normal Java array has a fixed length: once you create new String[5], it can never hold a sixth element. An ArrayList removes that limit. You simply call add(), and it makes room for the new element by itself.

Think of it as a notebook with removable pages. You can add a page at the end, insert one in the middle, tear one out, or jump straight to page 7. The notebook keeps the pages in order and gets thicker or thinner as needed.

Key features of ArrayList:

  • Ordered: elements keep the order in which you add them, and each one has an index starting at 0.
  • Dynamic size: the list grows automatically when it is full.
  • Fast random access: get(index) takes the same short time whatever the index, because the data is stored in an array.
  • Duplicates and null allowed: you can add the same value many times, and null is a valid element.
  • Objects only: it stores objects, so primitives such as int are stored as wrapper objects like Integer (Java converts them for you through autoboxing).
  • Not synchronized: it is not thread-safe. If several threads change the same list, you must add synchronization yourself.
  • Generic: ArrayList<String> accepts only strings, so type errors are caught at compile time.

2. Class Hierarchy and Declaration

ArrayList extends AbstractList and implements the List, RandomAccess, Cloneable and Serializable interfaces. Because List extends Collection, which extends Iterable, an ArrayList can be used anywhere a List, Collection or Iterable is expected.

ArrayList class hierarchy in Java

The class is declared like this in the JDK:

java.util.ArrayList
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

Here E is the type parameter: the type of elements the list holds. RandomAccess is a marker interface that tells algorithms the list supports fast access by index.

3. Your First ArrayList Program

This program creates a list of cities, adds three elements, reads one by index and loops through all of them.

ArrayListQuickStart.java
import java.util.ArrayList;
import java.util.List;

public class ArrayListQuickStart {
    public static void main(String[] args) {
        // Create an empty list that holds String values
        List<String> cities = new ArrayList<>();

        // Add elements (the list grows automatically)
        cities.add("Delhi");
        cities.add("Mumbai");
        cities.add("Pune");

        System.out.println("Cities: " + cities);
        System.out.println("First city: " + cities.get(0));
        System.out.println("Total cities: " + cities.size());

        // Loop through every element
        for (String city : cities) {
            System.out.println("Visiting " + city);
        }
    }
}
Output
Cities: [Delhi, Mumbai, Pune]
First city: Delhi
Total cities: 3
Visiting Delhi
Visiting Mumbai
Visiting Pune
Tip: declare the variable as List<String> and create it with new ArrayList<>(). Your code then depends on the interface, so you can switch to another list type later by changing one line. The empty <> (the diamond operator) lets Java infer the element type.

4. Creating an ArrayList (Constructors)

ArrayList has three constructors:

ConstructorWhat it does
ArrayList()Creates an empty list. Space for 10 elements is reserved when the first element is added.
ArrayList(int initialCapacity)Creates an empty list with room for the given number of elements. Use it when you know roughly how many elements you will add.
ArrayList(Collection<? extends E> c)Creates a list containing all elements of another collection, in that collection's iteration order.
CreateArrayList.java
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

public class CreateArrayList {
    public static void main(String[] args) {
        // 1. Empty list with the default capacity
        List<String> names = new ArrayList<>();

        // 2. Empty list with room for 500 elements before it has to grow
        List<Integer> orderIds = new ArrayList<>(500);

        // 3. A list that starts with a copy of another collection
        Set<String> skills = new TreeSet<>(Set.of("Java", "SQL", "Git"));
        List<String> skillList = new ArrayList<>(skills);

        // 4. A modifiable list filled with starting values
        List<String> colors = new ArrayList<>(List.of("Red", "Green", "Blue"));
        colors.add("Yellow");

        System.out.println(names + " size=" + names.size());
        System.out.println(orderIds + " size=" + orderIds.size());
        System.out.println(skillList);
        System.out.println(colors);
    }
}
Output
[] size=0
[] size=0
[Git, Java, SQL]
[Red, Green, Blue, Yellow]

Notice that orderIds has a size of 0 even though it has a capacity of 500. Capacity is reserved space; size is the number of elements actually stored.

5. Adding Elements

Use add(element) to append to the end, add(index, element) to insert at a position, and addAll() to add every element of another collection. When you insert in the middle, the elements after that position shift one place to the right.

AddElements.java
import java.util.ArrayList;
import java.util.List;

public class AddElements {
    public static void main(String[] args) {
        List<Integer> scores = new ArrayList<>();

        scores.add(40);          // add at the end
        scores.add(60);
        scores.add(80);
        System.out.println("After add():            " + scores);

        scores.add(1, 50);       // insert at index 1, others shift right
        System.out.println("After add(1, 50):       " + scores);

        List<Integer> bonus = List.of(90, 100);
        scores.addAll(bonus);    // add a whole collection at the end
        System.out.println("After addAll(bonus):    " + scores);

        scores.addAll(0, List.of(10, 20));   // insert a collection at index 0
        System.out.println("After addAll(0, [...]): " + scores);
    }
}
Output
After add():            [40, 60, 80]
After add(1, 50):       [40, 50, 60, 80]
After addAll(bonus):    [40, 50, 60, 80, 90, 100]
After addAll(0, [...]): [10, 20, 40, 50, 60, 80, 90, 100]

6. Accessing and Searching Elements

get(index) reads an element. indexOf() and lastIndexOf() find the position of a value (or return -1 when it is missing), and contains() tells you whether a value is present. subList(from, to) returns a view of part of the list, where from is included and to is excluded.

AccessElements.java
import java.util.ArrayList;
import java.util.List;

public class AccessElements {
    public static void main(String[] args) {
        List<String> fruits = new ArrayList<>(
                List.of("Apple", "Mango", "Banana", "Mango", "Grapes"));

        System.out.println("get(2):              " + fruits.get(2));
        System.out.println("indexOf(Mango):      " + fruits.indexOf("Mango"));
        System.out.println("lastIndexOf(Mango):  " + fruits.lastIndexOf("Mango"));
        System.out.println("indexOf(Kiwi):       " + fruits.indexOf("Kiwi"));
        System.out.println("contains(Banana):    " + fruits.contains("Banana"));
        System.out.println("size():              " + fruits.size());
        System.out.println("isEmpty():           " + fruits.isEmpty());
        System.out.println("subList(1, 3):       " + fruits.subList(1, 3));

        try {
            fruits.get(5);   // valid indexes are 0 to 4
        } catch (IndexOutOfBoundsException e) {
            System.out.println("Error: " + e.getMessage());
        }
    }
}
Output
get(2):              Banana
indexOf(Mango):      1
lastIndexOf(Mango):  3
indexOf(Kiwi):       -1
contains(Banana):    true
size():              5
isEmpty():           false
subList(1, 3):       [Mango, Banana]
Error: Index 5 out of bounds for length 5
Remember: valid indexes are 0 to size() - 1. Any other index throws IndexOutOfBoundsException.

7. Updating Elements

set(index, element) replaces the element at a position and returns the value it replaced. replaceAll() applies a function to every element.

UpdateElements.java
import java.util.ArrayList;
import java.util.List;

public class UpdateElements {
    public static void main(String[] args) {
        List<String> tasks = new ArrayList<>(List.of("Plan", "Code", "Tset", "Deploy"));
        System.out.println("Before: " + tasks);

        // set() replaces the element and returns the old value
        String old = tasks.set(2, "Test");
        System.out.println("Replaced '" + old + "' with 'Test'");
        System.out.println("After:  " + tasks);

        // replaceAll() changes every element using a function
        tasks.replaceAll(String::toUpperCase);
        System.out.println("Upper:  " + tasks);
    }
}
Output
Before: [Plan, Code, Tset, Deploy]
Replaced 'Tset' with 'Test'
After:  [Plan, Code, Test, Deploy]
Upper:  [PLAN, CODE, TEST, DEPLOY]

8. Removing Elements

You can remove by index, by value, all values found in another collection, all values that match a condition, or everything at once.

RemoveElements.java
import java.util.ArrayList;
import java.util.List;

public class RemoveElements {
    public static void main(String[] args) {
        List<String> langs = new ArrayList<>(
                List.of("Java", "Python", "Go", "Kotlin", "Rust", "JavaScript", "C"));
        System.out.println("Start:            " + langs);

        langs.remove(2);                        // by index -> removes "Go"
        System.out.println("remove(2):        " + langs);

        langs.remove("Rust");                   // by value -> removes "Rust"
        System.out.println("remove(\"Rust\"):   " + langs);

        langs.removeAll(List.of("C", "Python"));
        System.out.println("removeAll(...):   " + langs);

        langs.removeIf(s -> s.startsWith("Java"));
        System.out.println("removeIf(Java*):  " + langs);

        langs.clear();
        System.out.println("clear():          " + langs + " isEmpty=" + langs.isEmpty());

        // Careful with Integer lists: remove(int) vs remove(Object)
        List<Integer> nums = new ArrayList<>(List.of(10, 20, 30));
        nums.remove(1);                          // removes the element at index 1 (20)
        nums.remove(Integer.valueOf(10));        // removes the value 10
        System.out.println("Integer list:     " + nums);
    }
}
Output
Start:            [Java, Python, Go, Kotlin, Rust, JavaScript, C]
remove(2):        [Java, Python, Kotlin, Rust, JavaScript, C]
remove("Rust"):   [Java, Python, Kotlin, JavaScript, C]
removeAll(...):   [Java, Kotlin, JavaScript]
removeIf(Java*):  [Kotlin]
clear():          [] isEmpty=true
Integer list:     [30]
Watch out with List<Integer>: remove(1) calls remove(int index) and removes the element at index 1. To remove the value 1, write remove(Integer.valueOf(1)).

9. Iterating Over an ArrayList

There are five common ways to walk through an ArrayList. Choose the simplest one that does what you need.

IterateArrayList.java
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class IterateArrayList {
    public static void main(String[] args) {
        List<String> team = new ArrayList<>(List.of("Asha", "Ravi", "Meera"));

        // 1. Classic for loop (you need the index)
        for (int i = 0; i < team.size(); i++) {
            System.out.println(i + ": " + team.get(i));
        }

        // 2. Enhanced for loop (simplest way to read every element)
        for (String name : team) {
            System.out.print(name + " ");
        }
        System.out.println();

        // 3. forEach with a lambda
        team.forEach(name -> System.out.print(name.toUpperCase() + " "));
        System.out.println();

        // 4. Iterator (the safe way to remove while looping)
        Iterator<String> it = team.iterator();
        while (it.hasNext()) {
            if (it.next().startsWith("R")) {
                it.remove();
            }
        }
        System.out.println("After Iterator.remove(): " + team);

        // 5. ListIterator (can go backwards and replace elements)
        ListIterator<String> li = team.listIterator(team.size());
        while (li.hasPrevious()) {
            String name = li.previous();
            li.set(name + "!");
        }
        System.out.println("After ListIterator.set(): " + team);
    }
}
Output
0: Asha
1: Ravi
2: Meera
Asha Ravi Meera 
ASHA RAVI MEERA 
After Iterator.remove(): [Asha, Meera]
After ListIterator.set(): [Asha!, Meera!]
Way to loopUse it when
Classic for loopYou need the index of each element.
Enhanced for loopYou only read the elements. This is the most readable choice.
forEach(lambda)You want a short one-line action for each element.
IteratorYou need to remove elements while looping.
ListIteratorYou need to move backwards, or replace or insert elements while looping.

10. Avoiding ConcurrentModificationException

ArrayList's iterator is fail-fast. If the list is changed structurally (an element added or removed) while an enhanced for loop is running, the next step of the loop throws ConcurrentModificationException. This happens even with a single thread.

ConcurrentModification.java
import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.List;

public class ConcurrentModification {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6));

        try {
            for (Integer n : numbers) {
                if (n % 2 == 0) {
                    numbers.remove(n);   // WRONG: changes the list during the loop
                }
            }
        } catch (ConcurrentModificationException e) {
            System.out.println("Caught: " + e.getClass().getSimpleName());
        }

        // RIGHT: let the list remove the matching elements for you
        List<Integer> fresh = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6));
        fresh.removeIf(n -> n % 2 == 0);
        System.out.println("Odd numbers: " + fresh);
    }
}
Output
Caught: ConcurrentModificationException
Odd numbers: [1, 3, 5]

To remove while looping, use removeIf() or an explicit Iterator and its remove() method, as shown in the previous section.

11. Sorting an ArrayList

Use Collections.sort(list) or list.sort(comparator). Passing a Comparator lets you sort in reverse order, by length, or by any field of your own objects.

SortArrayList.java
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class SortArrayList {

    record Employee(String name, int salary) { }

    public static void main(String[] args) {
        List<String> words = new ArrayList<>(List.of("pear", "fig", "apple", "kiwi"));

        Collections.sort(words);                          // natural (A to Z) order
        System.out.println("A-Z:      " + words);

        words.sort(Comparator.reverseOrder());            // Z to A
        System.out.println("Z-A:      " + words);

        words.sort(Comparator.comparing(String::length)); // shortest first
        System.out.println("By size:  " + words);

        List<Employee> staff = new ArrayList<>(List.of(
                new Employee("Neha", 72000),
                new Employee("Arjun", 55000),
                new Employee("Kabir", 90000)));

        staff.sort(Comparator.comparingInt(Employee::salary).reversed());
        staff.forEach(e -> System.out.println(e.name() + " -> " + e.salary()));
    }
}
Output
A-Z:      [apple, fig, kiwi, pear]
Z-A:      [pear, kiwi, fig, apple]
By size:  [fig, pear, kiwi, apple]
Kabir -> 90000
Neha -> 72000
Arjun -> 55000

The sort is stable: elements that compare as equal keep their original order. That is why pear stays before kiwi when sorting by length. The example uses a Java 16+ record for Employee; a normal class with getters works the same way.

12. Converting Between ArrayList and Array

You will often need to move data between arrays and lists, for example when an older API expects an array.

ConvertArrayList.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ConvertArrayList {
    public static void main(String[] args) {
        // Array -> ArrayList (modifiable copy)
        String[] planets = {"Mercury", "Venus", "Earth"};
        List<String> planetList = new ArrayList<>(Arrays.asList(planets));
        planetList.add("Mars");
        System.out.println("List:  " + planetList);

        // ArrayList -> Array
        String[] back = planetList.toArray(new String[0]);
        System.out.println("Array: " + Arrays.toString(back) + " length=" + back.length);

        // Primitive int[] -> ArrayList<Integer> (needs boxing)
        int[] marks = {70, 85, 92};
        List<Integer> markList = new ArrayList<>(Arrays.stream(marks).boxed().toList());
        System.out.println("Marks: " + markList);

        // ArrayList<Integer> -> int[]
        int[] again = markList.stream().mapToInt(Integer::intValue).toArray();
        System.out.println("int[]: " + Arrays.toString(again));

        // Arrays.asList() is fixed-size: add() fails
        List<String> fixed = Arrays.asList("A", "B");
        try {
            fixed.add("C");
        } catch (UnsupportedOperationException e) {
            System.out.println("Arrays.asList() is fixed-size: " + e.getClass().getSimpleName());
        }
    }
}
Output
List:  [Mercury, Venus, Earth, Mars]
Array: [Mercury, Venus, Earth, Mars] length=4
Marks: [70, 85, 92]
int[]: [70, 85, 92]
Arrays.asList() is fixed-size: UnsupportedOperationException
Note: Arrays.asList() returns a fixed-size list backed by the array, and List.of() returns an unmodifiable list. Wrap either one in new ArrayList<>(...) when you need to add or remove elements.

13. Removing Duplicates

Because ArrayList allows duplicates, removing them is a common task. A LinkedHashSet keeps only unique values and remembers the order in which they first appeared. The Stream API's distinct() gives the same result.

RemoveDuplicates.java
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;

public class RemoveDuplicates {
    public static void main(String[] args) {
        List<String> visitors = new ArrayList<>(
                List.of("Riya", "Sam", "Riya", "John", "Sam", "Anil"));

        // LinkedHashSet removes duplicates and keeps the first-seen order
        List<String> unique = new ArrayList<>(new LinkedHashSet<>(visitors));
        System.out.println("Unique (Set):    " + unique);

        // Same result with streams
        List<String> unique2 = visitors.stream().distinct().toList();
        System.out.println("Unique (Stream): " + unique2);
    }
}
Output
Unique (Set):    [Riya, Sam, John, Anil]
Unique (Stream): [Riya, Sam, John, Anil]

14. How ArrayList Works Internally

Inside every ArrayList is a plain Java array called elementData, plus a size counter. Understanding these two fields explains almost everything about ArrayList's speed.

  1. Creation: new ArrayList<>() starts with a shared empty array, so it uses almost no memory until you add something.
  2. First add: an internal array with a capacity of 10 is created.
  3. Growing: when the array is full, a new array about 1.5 times bigger is created (newCapacity = oldCapacity + oldCapacity / 2), and all elements are copied into it. Capacity grows 10 → 15 → 22 → 33 → 49 and so on.
  4. Inserting or removing in the middle: elements after that position are shifted with System.arraycopy().
  5. Shrinking: removing elements never shrinks the internal array automatically. Call trimToSize() if you want to release the unused space.

Copying the array is expensive, but it happens rarely. Averaged over many calls, adding to the end costs constant time, which is called amortized O(1). If you know you will add many elements, create the list with a matching initial capacity, or call ensureCapacity(), to avoid repeated copying.

15. Time Complexity of Operations

OperationTimeWhy
get(i), set(i, e)O(1)Direct array index.
add(e) at the endO(1) amortizedUsually just writes to the next free slot; occasionally resizes.
add(i, e), remove(i)O(n)Elements after i must shift.
remove(size() - 1)O(1)Nothing to shift at the end.
contains(e), indexOf(e), remove(Object)O(n)Checks elements one by one with equals().
size(), isEmpty()O(1)Reads the stored size field.

If your program calls contains() very often on a large list, a HashSet (O(1) lookups) is usually a better choice.

16. ArrayList and Thread Safety

ArrayList is not synchronized. When two threads add to the same list at the same time, updates can be lost or an exception can be thrown. Use one of these thread-safe options instead:

  • Collections.synchronizedList(new ArrayList<>()): wraps every method in a lock. You must still synchronize manually while iterating.
  • CopyOnWriteArrayList: copies the array on every write. Reads are fast and never blocked, so it is ideal when reads far outnumber writes, such as lists of listeners.
ThreadSafeList.java
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class ThreadSafeList {
    public static void main(String[] args) throws InterruptedException {
        List<Integer> plain = new ArrayList<>();
        List<Integer> synced = Collections.synchronizedList(new ArrayList<>());
        List<Integer> cow = new CopyOnWriteArrayList<>();

        Runnable task = () -> {
            for (int i = 0; i < 10_000; i++) {
                synced.add(i);
                cow.add(i);
                try {
                    plain.add(i);   // not thread-safe
                } catch (ArrayIndexOutOfBoundsException ignored) {
                    // can happen when two threads resize the array at the same time
                }
            }
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);
        t1.start(); t2.start();
        t1.join();  t2.join();

        System.out.println("synchronizedList size:     " + synced.size());
        System.out.println("CopyOnWriteArrayList size: " + cow.size());
        System.out.println("plain ArrayList size:      " + plain.size() + " (expected 20000)");
    }
}
Output (the last number changes on every run)
synchronizedList size:     20000
CopyOnWriteArrayList size: 20000
plain ArrayList size:      19982 (expected 20000)

17. Common ArrayList Methods

MethodDescription
add(E e)Adds an element at the end. Returns true.
add(int index, E e)Inserts an element at the given position.
addAll(Collection c)Adds all elements of a collection at the end.
addAll(int index, Collection c)Inserts all elements of a collection at the given position.
get(int index)Returns the element at the given position.
set(int index, E e)Replaces the element at the given position and returns the old one.
remove(int index)Removes the element at the given position and returns it.
remove(Object o)Removes the first occurrence of the value. Returns true if found.
removeAll(Collection c)Removes every element that is also in the given collection.
retainAll(Collection c)Keeps only the elements that are also in the given collection.
removeIf(Predicate p)Removes every element that matches the condition.
clear()Removes all elements.
size()Returns the number of elements.
isEmpty()Returns true if the list has no elements.
contains(Object o)Returns true if the value is in the list.
indexOf(Object o)Index of the first occurrence, or -1.
lastIndexOf(Object o)Index of the last occurrence, or -1.
subList(int from, int to)Returns a view of the elements from from (included) to to (excluded).
sort(Comparator c)Sorts the list using the comparator (null means natural order).
replaceAll(UnaryOperator op)Replaces each element with the result of the function.
forEach(Consumer action)Runs the action for every element.
iterator(), listIterator()Return iterators for looping, removing and (with ListIterator) moving backwards.
toArray(), toArray(T[] a)Copy the elements into a new array.
ensureCapacity(int min)Grows the internal array in advance to hold at least min elements.
trimToSize()Shrinks the internal array to the current size.
clone()Returns a shallow copy: a new list that holds the same element objects.

18. ArrayList vs Array vs LinkedList vs Vector

FeatureArrayArrayListLinkedListVector
SizeFixedDynamicDynamicDynamic
PrimitivesYes (int[])No (wrappers)No (wrappers)No (wrappers)
Internal storageContiguous blockResizable arrayDoubly linked nodesResizable array
Access by indexO(1)O(1)O(n)O(1)
Insert or remove at the startNot possibleO(n)O(1)O(n)
Growth when fullCannot growAbout 50%One node at a time100% (doubles)
Thread-safeNoNoNoYes (synchronized)
Introduced inJDK 1.0JDK 1.2JDK 1.2JDK 1.0 (legacy)

Rule of thumb: use ArrayList by default. Use an array for fixed-size data or primitives where memory matters. Choose ArrayDeque (or LinkedList) when you mostly add and remove at both ends. Avoid Vector in new code; use a synchronized list or CopyOnWriteArrayList instead.

19. Best Practices

  • Program to the interface: write List<Order> orders = new ArrayList<>();, not ArrayList<Order> orders.
  • Always use generics: raw types such as new ArrayList() lose type safety and cause ClassCastException at runtime.
  • Set an initial capacity when you know the approximate size, to avoid repeated resizing.
  • Use isEmpty() instead of size() == 0; it reads more clearly.
  • Return an empty list, not null: callers can loop over it without null checks.
  • Override equals() and hashCode() in your own classes, otherwise contains(), indexOf() and remove(Object) will not find equal objects.
  • Return unmodifiable views (List.copyOf() or Collections.unmodifiableList()) from methods when callers should not change your internal list.

20. Common Mistakes

MistakeWhat happensFix
Removing inside an enhanced for loopConcurrentModificationExceptionUse removeIf() or Iterator.remove().
list.remove(5) on a List<Integer>Removes index 5, not the value 5list.remove(Integer.valueOf(5))
Calling add() on Arrays.asList() or List.of()UnsupportedOperationExceptionWrap it: new ArrayList<>(List.of(...))
Using get(size())IndexOutOfBoundsExceptionThe last index is size() - 1.
Sharing one ArrayList between threadsLost updates or exceptionsUse a synchronized list or CopyOnWriteArrayList.
Calling contains() in a loop over a big listO(n²) slownessCopy the values into a HashSet first.

21. Summary

  • ArrayList is a resizable, ordered, index-based list in java.util that allows duplicates and null.
  • It is backed by an array: reading by index is O(1), adding at the end is amortized O(1), and inserting or removing in the middle is O(n).
  • The default capacity is 10, and the list grows by about 50% when full.
  • Use removeIf() or an Iterator to remove elements while looping.
  • It is not thread-safe; use Collections.synchronizedList() or CopyOnWriteArrayList for shared lists.
  • Prefer it over arrays when the size changes, and over LinkedList and Vector in almost all cases.

Related Tutorials

Reference: Java SE 21 API: java.util.ArrayList