ArrayList
By the Syncfusion DevTutorials team · Last updated
Use ArrayList to add, remove, read, update, search, sort and loop through a resizable list, and understand capacity vs size.
Think about a train.
When more passengers turn up, the railway adds another coach. When fewer people travel, it removes one. The train is always the right length for the day. Each coach still has a number, so you can find your seat.
An ArrayList is like that train. It is a list that grows when you add items and shrinks when you remove them. Every item still has a position number, just like in an array.
In simple words: an ArrayList is an array that resizes itself.
What You Will Learn
In this lesson, you will learn:
- What an
ArrayListis, and how it differs from an array. - How to create an
ArrayList. - How to add, remove, read and update elements.
- How to search for elements.
- How to sort an
ArrayList. - Several ways to loop through an
ArrayList. - The most useful
ArrayListmethods. - The difference between capacity and size.
Start With a Working Example
Press Run.
A to-do list that grows, changes and shrinks
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<String> todo = new ArrayList<>();
todo.add("Buy milk");
todo.add("Pay bill");
todo.add("Call Ravi");
System.out.println("Start: " + todo);
todo.set(1, "Pay electricity bill");
todo.remove("Buy milk");
todo.add("Book tickets");
System.out.println("Now: " + todo);
System.out.println("Tasks left: " + todo.size());
System.out.println("First task: " + todo.get(0));
}
}
Expected output:
Start: [Buy milk, Pay bill, Call Ravi]
Now: [Pay electricity bill, Call Ravi, Book tickets]
Tasks left: 3
First task: Pay electricity bill
add puts items at the end. set changes one. remove takes one out, and the items after it move up to fill the gap. You never had to say how big the list was.
Try This
Add todo.add(0, "Wake up"); before the "Now" line. The new task goes to the front, and every other task moves back one place.
Introduction to ArrayList
An ArrayList is a class in java.util that implements the List interface.
It stores its elements in an array inside it. When that inner array is full and you add one more item, ArrayList automatically:
- creates a bigger array;
- copies every element across;
- adds the new item.
You never see this happen. You just keep calling add.
Key facts about an ArrayList:
- It keeps elements in the order you add them.
- It allows duplicates.
- It allows
nullelements. - It holds objects only. For numbers, use wrapper types like
Integer. - Reading by index is very fast.
ArrayList vs Array
| Array | ArrayList | |
|---|---|---|
| Size | Fixed when created | Grows and shrinks automatically |
| Created with | new String[5] or {...} | new ArrayList<>() |
| Holds primitives? | Yes, like int[] | No, use Integer |
| Number of elements | array.length | list.size() |
| Read an element | array[i] | list.get(i) |
| Change an element | array[i] = x | list.set(i, x) |
| Add or remove | Not possible without copying | add and remove |
| Printing | Needs Arrays.toString | Prints its contents directly |
| Speed | Slightly faster | Very slightly slower |
Use an array when the size never changes, or for large amounts of primitive data.
Use an ArrayList almost everywhere else.
Creating ArrayLists
There are several ways to create one.
ArrayList<String> a = new ArrayList<>(); // empty
List<String> b = new ArrayList<>(); // empty, using the interface type
ArrayList<String> c = new ArrayList<>(50); // empty, with room for 50 to start
ArrayList<String> d = new ArrayList<>(List.of("A", "B")); // starts with values
Notes:
- The type in angle brackets, like
<String>, says what the list can hold. List<String> b = new ArrayList<>()is the most common style. It uses theListinterface for the variable.List.of(...)creates a fixed list that cannot be changed. Wrapping it innew ArrayList<>(...)gives you a changeable copy.
Four ways to create an ArrayList
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
ArrayList<String> empty = new ArrayList<>();
List<Integer> marks = new ArrayList<>();
ArrayList<Double> prices = new ArrayList<>(100);
List<String> cities = new ArrayList<>(List.of("Chennai", "Pune", "Delhi"));
marks.add(85);
prices.add(19.99);
cities.add("Kochi");
System.out.println("Empty: " + empty + ", size " + empty.size());
System.out.println("Marks: " + marks);
System.out.println("Prices: " + prices);
System.out.println("Cities: " + cities);
}
}
Expected output:
Empty: [], size 0
Marks: [85]
Prices: [19.99]
Cities: [Chennai, Pune, Delhi, Kochi]
new ArrayList<>(100) still starts with size 0. The 100 only reserves room in advance. You will see why that matters under Capacity vs Size.
Adding Elements
| Method | What it does |
|---|---|
add(value) | Adds to the end |
add(index, value) | Inserts at a position; later items move back one place |
addAll(otherList) | Adds every item from another collection to the end |
addAll(index, otherList) | Inserts every item from another collection at a position |
Add to the end, at a position, or many at once
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> queue = new ArrayList<>();
queue.add("Ravi");
queue.add("Meena");
System.out.println(queue);
queue.add(0, "Asha");
System.out.println(queue);
queue.addAll(List.of("Arjun", "Divya"));
System.out.println(queue);
queue.add(2, "Kiran");
System.out.println(queue);
}
}
Expected output:
[Ravi, Meena]
[Asha, Ravi, Meena]
[Asha, Ravi, Meena, Arjun, Divya]
[Asha, Ravi, Kiran, Meena, Arjun, Divya]
add(0, "Asha") put Asha at the front, and everyone else moved back.
The index for add(index, value) can be anything from 0 to size(). Using size() is the same as adding to the end.
Removing Elements
| Method | What it does |
|---|---|
remove(index) | Removes the element at that position, and returns it |
remove(value) | Removes the first matching element; returns true if found |
removeAll(otherList) | Removes every element that is also in the other list |
removeIf(condition) | Removes every element that matches a condition |
clear() | Removes everything |
When an element is removed, every element after it moves forward one place. The list never has gaps.
Remove by position, by value, or by a rule
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> fruits = new ArrayList<>(List.of("Apple", "Mango", "Kiwi", "Mango", "Banana"));
String removed = fruits.remove(0);
System.out.println("Removed " + removed + ": " + fruits);
fruits.remove("Mango");
System.out.println("Removed first Mango: " + fruits);
fruits.removeIf(f -> f.startsWith("B"));
System.out.println("Removed names starting with B: " + fruits);
fruits.clear();
System.out.println("After clear: " + fruits + ", empty? " + fruits.isEmpty());
}
}
Expected output:
Removed Apple: [Mango, Kiwi, Mango, Banana]
Removed first Mango: [Kiwi, Mango, Banana]
Removed names starting with B: [Kiwi, Mango]
After clear: [], empty? true
remove("Mango") only removed the first Mango. The second one stayed.
removeIf takes a lambda, a short rule written as f -> f.startsWith("B"). It removes every element where the rule is true.
With a List<Integer>, remove(2) removes the element at index 2, not the value 2. To remove the value, write list.remove(Integer.valueOf(2)). This catches out a lot of people.
removeIf, forEach and sort take a lambda, a short rule like f -> f.startsWith("B"). You met lambdas with functional interfaces. Read the arrow as "becomes": each element f becomes true or false.
Accessing Elements
get(index) returns the element at a position. Indexes start at 0, and the last index is size() - 1.
list.get(0) // first element
list.get(list.size() - 1) // last element
An index outside that range stops the program with an IndexOutOfBoundsException.
Updating Elements
set(index, value) replaces the element at a position. It returns the old value.
set does not change the size. It can only replace an element that already exists.
Read with get, replace with set
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> scores = new ArrayList<>(List.of(70, 85, 60, 92));
System.out.println("First: " + scores.get(0));
System.out.println("Last: " + scores.get(scores.size() - 1));
int old = scores.set(2, 75);
System.out.println("Changed " + old + " to " + scores.get(2));
for (int i = 0; i < scores.size(); i++) {
scores.set(i, scores.get(i) + 5);
}
System.out.println("After 5 bonus marks: " + scores);
}
}
Expected output:
First: 70
Last: 92
Changed 60 to 75
After 5 bonus marks: [75, 90, 80, 97]
The loop reads each mark with get, adds 5, and writes it back with set.
Searching Elements
| Method | Returns |
|---|---|
contains(value) | true if the value is in the list |
indexOf(value) | The index of the first match, or -1 |
lastIndexOf(value) | The index of the last match, or -1 |
isEmpty() | true if the list has no elements |
These methods use equals() to compare, so they work correctly with strings.
Find whether, and where, a value appears
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> seats = new ArrayList<>(List.of("A1", "A2", "B4", "A2", "C1"));
System.out.println("Has B4? " + seats.contains("B4"));
System.out.println("Has D9? " + seats.contains("D9"));
System.out.println("First A2 at: " + seats.indexOf("A2"));
System.out.println("Last A2 at: " + seats.lastIndexOf("A2"));
System.out.println("D9 at: " + seats.indexOf("D9"));
}
}
Expected output:
Has B4? true
Has D9? false
First A2 at: 1
Last A2 at: 3
D9 at: -1
indexOf returns -1 for a value that is not there. Always check for -1 before using the result as an index.
These searches check the elements one by one, from the start. For very large lists where you search often, a HashSet or HashMap is much faster.
Sorting Elements
There are two common ways to sort an ArrayList:
Collections.sort(list)sorts in natural order: numbers from small to large, text alphabetically.list.sort(comparator)sorts with your own rule.
A comparator is a rule that says how to compare two elements. Java has ready-made ones:
| Comparator | Sorts |
|---|---|
Comparator.naturalOrder() | Small to large, A to Z |
Comparator.reverseOrder() | Large to small, Z to A |
Comparator.comparing(String::length) | By a value you choose, here the length |
Sorting changes the list itself.
Natural order, reverse order and a custom rule
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> marks = new ArrayList<>(List.of(72, 95, 58, 81));
Collections.sort(marks);
System.out.println("Low to high: " + marks);
marks.sort(Comparator.reverseOrder());
System.out.println("High to low: " + marks);
List<String> names = new ArrayList<>(List.of("Meena", "Asha", "Ravi", "Arjun"));
Collections.sort(names);
System.out.println("A to Z: " + names);
names.sort(Comparator.comparing(String::length));
System.out.println("By length: " + names);
}
}
Expected output:
Low to high: [58, 72, 81, 95]
High to low: [95, 81, 72, 58]
A to Z: [Arjun, Asha, Meena, Ravi]
By length: [Asha, Ravi, Arjun, Meena]
String::length is a method reference. It is a short way to say "use each string's length()". Names with the same length keep their previous order.
Iterating through ArrayList
There are four common ways to loop through an ArrayList.
1. Indexed for Loop
Use it when you need the position, or want to change elements with set.
2. for-each Loop
The simplest way to read every element.
3. Iterator
Use it when you need to remove elements while looping.
4. forEach Method
list.forEach(...) runs a lambda on every element. It is short and modern.
Four ways to visit every element
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> colours = new ArrayList<>(List.of("Red", "Green", "Blue"));
System.out.println("1. Indexed for:");
for (int i = 0; i < colours.size(); i++) {
System.out.println(" " + i + ": " + colours.get(i));
}
System.out.println("2. for-each:");
for (String c : colours) {
System.out.println(" " + c);
}
System.out.println("3. Iterator:");
Iterator<String> it = colours.iterator();
while (it.hasNext()) {
System.out.println(" " + it.next());
}
System.out.println("4. forEach:");
colours.forEach(c -> System.out.println(" " + c.toUpperCase()));
}
}
Expected output:
1. Indexed for:
0: Red
1: Green
2: Blue
2. for-each:
Red
Green
Blue
3. Iterator:
Red
Green
Blue
4. forEach:
RED
GREEN
BLUE
| Loop | Gives the index? | Can remove safely? | Best for |
|---|---|---|---|
Indexed for | Yes | Only with care | Positions, using set |
| for-each | No | No | Simple reading |
Iterator | No | Yes | Removing while looping |
forEach | No | No | Short one-line actions |
ArrayList Methods
| Method | What it does | Example |
|---|---|---|
add(e) | Adds to the end | list.add("A") |
add(i, e) | Inserts at index i | list.add(0, "A") |
addAll(c) | Adds every element of c | list.addAll(other) |
get(i) | Returns the element at i | list.get(2) |
set(i, e) | Replaces the element at i | list.set(2, "B") |
remove(i) | Removes by index | list.remove(0) |
remove(o) | Removes the first match | list.remove("A") |
removeIf(rule) | Removes all that match | list.removeIf(x -> x < 0) |
size() | Number of elements | list.size() |
isEmpty() | true if empty | list.isEmpty() |
contains(o) | true if present | list.contains("A") |
indexOf(o) | First index, or -1 | list.indexOf("A") |
clear() | Removes everything | list.clear() |
sort(cmp) | Sorts with a rule | list.sort(Comparator.reverseOrder()) |
subList(a, b) | A view of indexes a up to b | list.subList(0, 3) |
toArray(...) | Copies into an array | list.toArray(new String[0]) |
subList, toArray and a few helpers
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> steps = new ArrayList<>(List.of(4200, 8100, 6500, 10200, 7300));
System.out.println("First three days: " + steps.subList(0, 3));
System.out.println("Best day: " + Collections.max(steps));
System.out.println("Worst day: " + Collections.min(steps));
Collections.reverse(steps);
System.out.println("Reversed: " + steps);
Integer[] asArray = steps.toArray(new Integer[0]);
System.out.println("As an array: " + Arrays.toString(asArray));
}
}
Expected output:
First three days: [4200, 8100, 6500]
Best day: 10200
Worst day: 4200
Reversed: [7300, 10200, 6500, 8100, 4200]
As an array: [7300, 10200, 6500, 8100, 4200]
Collections (with an s) is a helper class full of static methods for collections, like max, min, reverse and sort.
subList(0, 3) returns indexes 0, 1 and 2. The end index is not included, just like substring.
Capacity vs Size
These two words sound alike, but they mean different things.
- Size is how many elements the list holds right now. You read it with
size(). - Capacity is how many elements the inner array has room for before it must grow. You cannot read it directly.
Think of a bus with 40 seats and 12 passengers. The capacity is 40. The size is 12.
When the size reaches the capacity and you add one more element, ArrayList creates a bigger inner array, usually about one and a half times larger, and copies everything across. Then it adds the new element.
add #1 → capacity 10, size 1
...
add #10 → capacity 10, size 10 (full)
add #11 → grows to capacity 15, copies 10 elements, size 11
That copying takes time. If you know you will add many elements, you can set the starting capacity yourself:
List<Integer> big = new ArrayList<>(10000);
This avoids many grow-and-copy steps. The list still starts with size 0.
Capacity is reserved room, size is real items
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>(100);
System.out.println("Size after new ArrayList<>(100): " + list.size());
for (int i = 1; i <= 5; i++) {
list.add(i * 10);
}
System.out.println("Size after 5 adds: " + list.size());
list.ensureCapacity(500);
list.trimToSize();
System.out.println("Size is still: " + list.size());
System.out.println("Contents: " + list);
}
}
Expected output:
Size after new ArrayList<>(100): 0
Size after 5 adds: 5
Size is still: 5
Contents: [10, 20, 30, 40, 50]
ensureCapacity(500) reserves room for 500 elements. trimToSize() shrinks the inner array down to exactly the current size, to save memory. Neither one changes the size.
| Size | Capacity | |
|---|---|---|
| Meaning | Elements actually stored | Room in the inner array |
| Read with | size() | Not directly readable |
| Changes when | You add or remove | The list grows, or you call ensureCapacity / trimToSize |
| Starts at | 0 | 10 by default, or the number you pass in |
Easy Way to Remember: size = passengers on the bus. Capacity = seats on the bus.
Common mistakes
The following mistakes are common when using ArrayList. Each row shows what you see, why it happens and how to fix it.
| Symptom | Cause | Fix |
|---|---|---|
array required, but ArrayList found | [ ] or length used on a list | Use get(i) and size() |
IndexOutOfBoundsException | An index of size() or more | Use indexes 0 to size() - 1 |
| The wrong number is removed | remove(int) removed by index | Use remove(Integer.valueOf(x)) |
UnsupportedOperationException | The list came from List.of | Copy it into new ArrayList<>(...) |
set fails on a new list | set cannot add new elements | Use add |
ConcurrentModificationException | The list changed during a for-each loop | Use removeIf or an Iterator |
What to Remember
- An
ArrayListis a resizable list. It keeps insertion order and allows duplicates. - Create one with
List<String> list = new ArrayList<>();. It holds objects, so useIntegerfor numbers. addto insert,removeto delete,getto read andsetto replace. Later elements shift to fill gaps.contains,indexOfandlastIndexOfsearch the list.indexOfreturns-1when nothing matches.- Sort with
Collections.sort(list)orlist.sort(comparator). - Loop with an indexed
for, a for-each, anIteratororforEach. Remove while looping with anIteratororremoveIf. - Size is how many elements it holds. Capacity is how much room its inner array has.
Next: Set and Map