ArrayList
ArrayList is Java’s go-to resizable array. Unlike a plain array whose size is fixed at creation, an ArrayList grows (and shrinks) automatically as you add or remove elements — making it the workhorse of everyday Java programming.
What is ArrayList?
ArrayList<E> lives in the java.util package and implements the List interface. Under the hood it wraps a regular Object[] array, but you never have to manage its capacity yourself.
import java.util.ArrayList;
public class BasicList {
public static void main(String[] args) {
ArrayList<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");
System.out.println(fruits);
}
}
Output:
[Apple, Banana, Cherry]
Creating an ArrayList
There are several ways to construct one:
import java.util.ArrayList;
import java.util.List;
public class CreatingArrayList {
public static void main(String[] args) {
// Default initial capacity (10)
ArrayList<Integer> nums = new ArrayList<>();
// With an initial capacity hint (avoids early resizing)
ArrayList<Integer> sized = new ArrayList<>(50);
// From an existing collection
List<String> copy = new ArrayList<>(List.of("X", "Y", "Z"));
System.out.println(copy);
}
}
Output:
[X, Y, Z]
Tip: If you already know the approximate number of elements, pass that as the initial capacity. It avoids unnecessary array reallocations and improves performance.
Common Operations
Adding Elements
import java.util.ArrayList;
public class AddElements {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("One"); // append
list.add("Three");
list.add(1, "Two"); // insert at index 1
System.out.println(list); // [One, Two, Three]
}
}
Output:
[One, Two, Three]
Accessing Elements
import java.util.ArrayList;
public class AccessElements {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>(List.of("A", "B", "C"));
String first = list.get(0); // "A"
int idx = list.indexOf("B"); // 1
int size = list.size(); // 3
System.out.println(first + " at index " + idx + ", size=" + size);
}
}
Output:
A at index 1, size=3
Updating and Removing
import java.util.ArrayList;
public class ModifyList {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("cat");
list.add("dog");
list.add("bird");
list.set(1, "fish"); // replace "dog" → "fish"
list.remove("cat"); // remove by value
list.remove(0); // remove by index (now removes "fish")
System.out.println(list); // [bird]
}
}
Output:
[bird]
Warning:
remove(int index)andremove(Object o)are different overloads. With anArrayList<Integer>, callingremove(1)removes the element at index 1. To remove the value 1, useremove(Integer.valueOf(1)). See Autoboxing & Unboxing for more context.
Iterating
You can loop over an ArrayList in multiple ways:
import java.util.ArrayList;
import java.util.Iterator;
public class IterateList {
public static void main(String[] args) {
ArrayList<String> colors = new ArrayList<>();
colors.add("Red");
colors.add("Green");
colors.add("Blue");
// 1. for-each (cleanest)
for (String c : colors) {
System.out.print(c + " ");
}
System.out.println();
// 2. indexed for loop
for (int i = 0; i < colors.size(); i++) {
System.out.print(colors.get(i) + " ");
}
System.out.println();
// 3. Iterator (safe removal during iteration)
Iterator<String> it = colors.iterator();
while (it.hasNext()) {
String c = it.next();
if (c.equals("Green")) it.remove();
}
System.out.println(colors);
}
}
Output:
Red Green Blue
Red Green Blue
[Red, Blue]
Warning: Never call
list.remove()inside a for-each loop directly — it throwsConcurrentModificationException. Use anIteratoror theremoveIf()method instead.
Bulk Operations
import java.util.ArrayList;
import java.util.Collections;
public class BulkOps {
public static void main(String[] args) {
ArrayList<Integer> nums = new ArrayList<>();
nums.add(3); nums.add(1); nums.add(4); nums.add(1); nums.add(5);
Collections.sort(nums); // sort ascending
System.out.println("Sorted: " + nums);
nums.removeIf(n -> n < 3); // remove all < 3 (Java 8+)
System.out.println("Filtered: " + nums);
nums.replaceAll(n -> n * 2); // double every element
System.out.println("Doubled: " + nums);
}
}
Output:
Sorted: [1, 1, 3, 4, 5]
Filtered: [3, 4, 5]
Doubled: [6, 8, 10]
Useful ArrayList Methods — Quick Reference
| Method | What it does |
|---|---|
add(E e) | Appends element to the end |
add(int i, E e) | Inserts at index i |
get(int i) | Returns element at index i |
set(int i, E e) | Replaces element at index i |
remove(int i) | Removes element at index i |
remove(Object o) | Removes first occurrence of o |
size() | Number of elements |
isEmpty() | true if size is 0 |
contains(Object o) | true if element exists |
indexOf(Object o) | First index of o, or -1 |
clear() | Removes all elements |
addAll(Collection c) | Appends all elements from c |
subList(from, to) | View of a portion of the list |
toArray() | Returns an Object[] snapshot |
trimToSize() | Shrinks internal array to current size |
Sorting an ArrayList
You can sort with Collections.sort() or list.sort() (Java 8+):
import java.util.ArrayList;
import java.util.Comparator;
public class SortList {
public static void main(String[] args) {
ArrayList<String> names = new ArrayList<>();
names.add("Charlie"); names.add("Alice"); names.add("Bob");
names.sort(Comparator.naturalOrder()); // alphabetical
System.out.println("Asc: " + names);
names.sort(Comparator.reverseOrder()); // reverse
System.out.println("Desc: " + names);
names.sort(Comparator.comparingInt(String::length)); // by length
System.out.println("By length: " + names);
}
}
Output:
Asc: [Alice, Bob, Charlie]
Desc: [Charlie, Bob, Alice]
By length: [Bob, Alice, Charlie]
For custom objects, see Comparable and Comparator.
Converting Between Array and ArrayList
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ConvertArrayList {
public static void main(String[] args) {
// Array → ArrayList
String[] arr = {"x", "y", "z"};
ArrayList<String> list = new ArrayList<>(Arrays.asList(arr));
list.add("w"); // mutable, unlike Arrays.asList alone
System.out.println(list);
// ArrayList → Array
String[] back = list.toArray(new String[0]);
System.out.println(Arrays.toString(back));
}
}
Output:
[x, y, z, w]
[x, y, z, w]
Under the Hood
When you create new ArrayList<>(), Java allocates an internal Object[] with a default capacity of 10. Here is what happens as you add elements:
- Normal add — the element is stored at the next free slot. O(1) amortized.
- Capacity exceeded — Java allocates a new array of size
oldCapacity * 1.5(approximately), copies all existing elements into it, then adds the new element. This grow operation is O(n) but happens infrequently. trimToSize()— shrinks the backing array to exactlysize(), saving memory if the list has stopped growing.
Because elements sit in a contiguous block of memory, get(i) is O(1) — just a direct array offset. In contrast, insertion or removal in the middle is O(n) because subsequent elements must shift. If you do a lot of middle-insertions, consider LinkedList instead.
Note:
ArrayListis not thread-safe. For concurrent access, wrap it withCollections.synchronizedList()or useCopyOnWriteArrayListfrom the Concurrent Collections package.
The iterator returned by ArrayList is fail-fast: it tracks an internal modCount. If the list is structurally modified outside the iterator, the next next() or remove() call throws ConcurrentModificationException. This is a safety check, not a guarantee — see the Java Memory Model page for thread-safety nuances.
ArrayList vs Array — When to Use Which
| Feature | int[] / String[] | ArrayList<Integer> / ArrayList<String> |
|---|---|---|
| Size | Fixed at creation | Grows/shrinks automatically |
| Performance | Slightly faster (no boxing) | Tiny overhead from autoboxing |
| Primitives | Yes (int, double, …) | No — stores objects only |
| Utility methods | None built-in | Rich API (sort, search, etc.) |
| Generics | No | Yes |
Use a plain array when size is known, performance is critical, or you need to store primitives without boxing overhead. Use ArrayList for everything else.
Related Topics
- List Interface — the contract
ArrayListimplements, and why coding to an interface matters - LinkedList — the other popular
Listimplementation; great for frequent insertions/deletions - ArrayList vs LinkedList — a side-by-side performance and use-case comparison
- Comparable — implement natural ordering so your objects sort correctly in any
List - Iterator — safely traverse and remove elements from any collection
- Collections Utility Class — sort, shuffle, reverse, and more built-in helpers for
ArrayList