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:

  1. What an ArrayList is, and how it differs from an array.
  2. How to create an ArrayList.
  3. How to add, remove, read and update elements.
  4. How to search for elements.
  5. How to sort an ArrayList.
  6. Several ways to loop through an ArrayList.
  7. The most useful ArrayList methods.
  8. 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:

  1. creates a bigger array;
  2. copies every element across;
  3. 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 null elements.
  • It holds objects only. For numbers, use wrapper types like Integer.
  • Reading by index is very fast.

ArrayList vs Array

ArrayArrayList
SizeFixed when createdGrows and shrinks automatically
Created withnew String[5] or {...}new ArrayList<>()
Holds primitives?Yes, like int[]No, use Integer
Number of elementsarray.lengthlist.size()
Read an elementarray[i]list.get(i)
Change an elementarray[i] = xlist.set(i, x)
Add or removeNot possible without copyingadd and remove
PrintingNeeds Arrays.toStringPrints its contents directly
SpeedSlightly fasterVery 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 the List interface for the variable.
  • List.of(...) creates a fixed list that cannot be changed. Wrapping it in new 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

MethodWhat 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

MethodWhat 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

MethodReturns
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:

ComparatorSorts
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
LoopGives the index?Can remove safely?Best for
Indexed forYesOnly with carePositions, using set
for-eachNoNoSimple reading
IteratorNoYesRemoving while looping
forEachNoNoShort one-line actions

ArrayList Methods

MethodWhat it doesExample
add(e)Adds to the endlist.add("A")
add(i, e)Inserts at index ilist.add(0, "A")
addAll(c)Adds every element of clist.addAll(other)
get(i)Returns the element at ilist.get(2)
set(i, e)Replaces the element at ilist.set(2, "B")
remove(i)Removes by indexlist.remove(0)
remove(o)Removes the first matchlist.remove("A")
removeIf(rule)Removes all that matchlist.removeIf(x -> x < 0)
size()Number of elementslist.size()
isEmpty()true if emptylist.isEmpty()
contains(o)true if presentlist.contains("A")
indexOf(o)First index, or -1list.indexOf("A")
clear()Removes everythinglist.clear()
sort(cmp)Sorts with a rulelist.sort(Comparator.reverseOrder())
subList(a, b)A view of indexes a up to blist.subList(0, 3)
toArray(...)Copies into an arraylist.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.

SizeCapacity
MeaningElements actually storedRoom in the inner array
Read withsize()Not directly readable
Changes whenYou add or removeThe list grows, or you call ensureCapacity / trimToSize
Starts at010 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.

SymptomCauseFix
array required, but ArrayList found[ ] or length used on a listUse get(i) and size()
IndexOutOfBoundsExceptionAn index of size() or moreUse indexes 0 to size() - 1
The wrong number is removedremove(int) removed by indexUse remove(Integer.valueOf(x))
UnsupportedOperationExceptionThe list came from List.ofCopy it into new ArrayList<>(...)
set fails on a new listset cannot add new elementsUse add
ConcurrentModificationExceptionThe list changed during a for-each loopUse removeIf or an Iterator

What to Remember

  • An ArrayList is a resizable list. It keeps insertion order and allows duplicates.
  • Create one with List<String> list = new ArrayList<>();. It holds objects, so use Integer for numbers.
  • add to insert, remove to delete, get to read and set to replace. Later elements shift to fill gaps.
  • contains, indexOf and lastIndexOf search the list. indexOf returns -1 when nothing matches.
  • Sort with Collections.sort(list) or list.sort(comparator).
  • Loop with an indexed for, a for-each, an Iterator or forEach. Remove while looping with an Iterator or removeIf.
  • Size is how many elements it holds. Capacity is how much room its inner array has.

Next: Set and Map