ArrayList in Java is a resizable array implementation from the Java Collections Framework. Unlike a regular Java array, an ArrayList can automatically grow or shrink as elements are added and removed.
ArrayList is one of the most commonly used collection types in Java because it provides fast indexed access while allowing the collection size to change dynamically. It is useful for storing ordered collections such as users, products, tasks, messages, and other application data.
What Is ArrayList in Java?
ArrayList implements the
List interface and internally uses a dynamically resized
array to store its elements.
Because it is a List, ArrayList maintains insertion order, allows duplicate elements,
and provides access to elements using indexes starting from 0.
import java.util.ArrayList;
import java.util.List;
List<String> languages = new ArrayList<>();
languages.add("Java");
languages.add("Python");
languages.add("C#");
System.out.println(languages);
Creating an ArrayList
An ArrayList can be declared using the List interface
and initialized with the ArrayList implementation.
This is generally preferred because the code depends on the interface rather than a specific implementation.
import java.util.ArrayList;
import java.util.List;
List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
names.add("Charlie");
Java collections use generic types, so ArrayList<String>
accepts strings, while ArrayList<Integer> accepts integer values.
Collections work with objects, so primitive values such as int
use wrapper types such as Integer.
Adding Elements to ArrayList
The add() method appends an element to the end of the list.
List<String> skills = new ArrayList<>();
skills.add("Java");
skills.add("Spring");
skills.add("SQL");
System.out.println(skills);
You can also insert an element at a specific index by using the overloaded
add(index, element) method.
Existing elements at that position and after it are shifted to the right.
List<String> skills = new ArrayList<>();
skills.add("Java");
skills.add("SQL");
skills.add("Spring");
skills.add(1, "C#");
System.out.println(skills);
Accessing ArrayList Elements
Use the get() method to retrieve an element at a particular index.
ArrayList provides constant-time indexed access in typical usage.
List<String> languages = new ArrayList<>();
languages.add("Java");
languages.add("Python");
languages.add("JavaScript");
String first = languages.get(0);
String second = languages.get(1);
System.out.println(first);
System.out.println(second);
Accessing an index outside the valid range throws an
IndexOutOfBoundsException.
Updating an ArrayList Element
The set() method replaces the element at a specified index.
It does not change the size of the list.
List<String> languages = new ArrayList<>();
languages.add("Java");
languages.add("Python");
languages.add("C#");
languages.set(1, "TypeScript");
System.out.println(languages);
After calling set(1, "TypeScript"), the element at index
1 is replaced. No additional element is inserted.
Removing Elements from ArrayList
ArrayList provides several ways to remove elements. You can remove an element by index or remove a matching object.
List<String> languages = new ArrayList<>();
languages.add("Java");
languages.add("Python");
languages.add("C#");
languages.remove(1);
System.out.println(languages);
To remove an object rather than an index, pass the object itself.
languages.remove("C#");
System.out.println(languages);
Removing Integer Values
A common source of confusion occurs with ArrayList<Integer>
because remove(int) removes by index.
To remove an Integer value, explicitly use Integer.valueOf().
List<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);
numbers.add(30);
numbers.remove(Integer.valueOf(20));
System.out.println(numbers);
Finding Elements in ArrayList
ArrayList provides methods such as contains(),
indexOf(), and lastIndexOf()
for searching elements.
List<String> languages = new ArrayList<>();
languages.add("Java");
languages.add("Python");
languages.add("JavaScript");
languages.add("Java");
System.out.println(languages.contains("Python"));
System.out.println(languages.indexOf("Java"));
System.out.println(languages.lastIndexOf("Java"));
indexOf() returns the first matching index,
while lastIndexOf() returns the last matching index.
If no matching element exists, these methods return -1.
Checking the Size of an ArrayList
Use the size() method to determine how many elements are currently stored.
List<String> users = new ArrayList<>();
users.add("Alice");
users.add("Bob");
users.add("Charlie");
System.out.println(users.size());
The value returned by size() represents the number of elements,
not the internal capacity of the ArrayList.
Iterating Through an ArrayList
ArrayList can be traversed using an enhanced for loop,
a traditional indexed loop, or the forEach() method.
List<String> languages = new ArrayList<>();
languages.add("Java");
languages.add("Python");
languages.add("C#");
for (String language : languages) {
System.out.println(language);
}
When the index is required, an indexed loop can be used.
for (int i = 0; i < languages.size(); i++) {
System.out.println(i + ": " + languages.get(i));
}
Sorting an ArrayList
The Collections.sort() method can sort elements in their natural order.
For custom ordering, a comparator can be supplied.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
List<Integer> numbers = new ArrayList<>();
numbers.add(40);
numbers.add(10);
numbers.add(30);
numbers.add(20);
Collections.sort(numbers);
System.out.println(numbers);
For descending order, use Collections.reverseOrder().
Collections.sort(numbers, Collections.reverseOrder());
System.out.println(numbers);
Adding Multiple Elements
The addAll() method adds all elements from another collection.
List<String> backend = new ArrayList<>();
backend.add("Java");
backend.add("C#");
List<String> additional = new ArrayList<>();
additional.add("Python");
additional.add("Go");
backend.addAll(additional);
System.out.println(backend);
Removing Multiple Elements
Java provides methods such as removeAll() and
removeIf() for removing multiple elements based on a collection or condition.
List<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(15);
numbers.add(20);
numbers.add(25);
numbers.add(30);
numbers.removeIf(number -> number > 20);
System.out.println(numbers);
The removeIf() method is especially useful when elements
should be removed according to a condition.
Clearing an ArrayList
The clear() method removes all elements from the ArrayList.
List<String> users = new ArrayList<>();
users.add("Alice");
users.add("Bob");
users.clear();
System.out.println(users);
System.out.println(users.isEmpty());
ArrayList Capacity
An ArrayList has a current size representing the number of stored elements and an internal capacity representing the amount of storage available before the backing array needs to be resized.
The capacity is managed internally by Java. When additional space is required, the implementation can allocate a larger backing array and copy the existing elements into it. This resizing is why adding to the end of an ArrayList is considered O(1) amortized rather than O(1) for every individual insertion.
Initial Capacity
If the approximate number of elements is known in advance, an initial capacity can be supplied when creating an ArrayList. This can reduce the number of internal resizing operations as the collection grows.
import java.util.ArrayList;
ArrayList<String> users = new ArrayList<>(100);
users.add("Alice");
users.add("Bob");
Initial capacity affects internal storage allocation; it does not limit the maximum number of elements that the ArrayList can contain.
ArrayList Time Complexity
Understanding ArrayList complexity helps when choosing it for performance-sensitive code.
| Operation | Typical Complexity | Reason |
|---|---|---|
| get(index) | O(1) | Direct indexed access |
| set(index, value) | O(1) | Direct replacement |
| add(value) | O(1) amortized | Append to the backing array |
| add(index, value) | O(n) | Elements may need to be shifted |
| get(index) search | O(1) | When the index is already known |
| contains(value) | O(n) | May scan the list |
| remove(index) | O(n) | Elements may need to be shifted |
| sort() | O(n log n) | Uses Java's list sorting implementation |
ArrayList vs Array
Both arrays and ArrayList store ordered elements, but they are designed for different requirements.
| Feature | Array | ArrayList |
|---|---|---|
| Size | Fixed | Dynamic |
| Indexed access | O(1) | O(1) |
| Primitive types | Supported | Use wrapper types |
| Built-in collection methods | Limited | Rich API |
ArrayList vs LinkedList
Both implement the List interface, but they use different
underlying structures and therefore have different performance characteristics.
| Feature | ArrayList | LinkedList |
|---|---|---|
| Underlying structure | Dynamic array | Doubly linked list |
| get(index) | O(1) | O(n) |
| Append | O(1) amortized | O(1) |
| Memory layout | Array-backed | Separate linked nodes |
For many general-purpose list workloads, ArrayList is a practical default because indexed access is fast and its array-backed storage has good locality. LinkedList is more specialized and should be selected when its particular list or deque behavior fits the workload.
Working with Custom Objects
ArrayList can store custom Java objects, making it useful for application-level data.
import java.util.ArrayList;
import java.util.List;
class User {
String name;
int age;
User(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Main {
public static void main(String[] args) {
List<User> users = new ArrayList<>();
users.add(new User("Alice", 25));
users.add(new User("Bob", 30));
for (User user : users) {
System.out.println(user.name + " - " + user.age);
}
}
}
ArrayList with Streams
ArrayList works naturally with the Java Stream API, which can be useful for filtering, transforming, and processing collections.
import java.util.ArrayList;
import java.util.List;
List<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(15);
numbers.add(20);
numbers.add(25);
List<Integer> evenNumbers = numbers.stream()
.filter(number -> number % 2 == 0)
.toList();
System.out.println(evenNumbers);
Converting ArrayList to an Array
The toArray() method can convert an ArrayList into an array.
List<String> languages = new ArrayList<>();
languages.add("Java");
languages.add("Python");
languages.add("C#");
String[] result = languages.toArray(new String[0]);
for (String language : result) {
System.out.println(language);
}
Common ArrayList Mistakes
- Trying to access an index that does not exist.
- Using
set()when a new element should actually be inserted. - Confusing
remove(index)withremove(object). - Expecting
contains()to provide constant-time lookup. - Using ArrayList when unique-value semantics are required instead of a Set.
- Assuming ArrayList is thread-safe by default.
- Using an excessively large initial capacity without a practical reason.
- Choosing LinkedList solely because insertion is theoretically O(1), without considering the cost of locating the position.
When Should You Use ArrayList?
ArrayList is a strong choice when an application needs a dynamically sized, ordered collection with frequent indexed access.
- You need a collection that grows dynamically.
- You frequently access elements by index.
- You need to preserve insertion order.
- Duplicate values are allowed.
- Most additions occur at the end of the collection.
- You need Java Collection Framework methods such as filtering, sorting, searching, and bulk operations.
Practical Example: Managing Products
A simple application can use an ArrayList to maintain a collection of products. The list can grow as new products are added and can be searched or updated using standard methods.
import java.util.ArrayList;
import java.util.List;
class Product {
String name;
double price;
Product(String name, double price) {
this.name = name;
this.price = price;
}
}
public class Main {
public static void main(String[] args) {
List<Product> products = new ArrayList<>();
products.add(new Product("Keyboard", 45.99));
products.add(new Product("Mouse", 25.50));
products.add(new Product("Monitor", 199.99));
for (Product product : products) {
System.out.println(
product.name + " - $" + product.price
);
}
}
}
Key Takeaways
ArrayListis a resizable array implementation of the JavaListinterface.- It maintains insertion order and allows duplicate elements.
- Indexed access using
get()is typically O(1). - Adding at the end is O(1) amortized, while inserting in the middle can require O(n) shifting.
- Searching with methods such as
contains()is O(n). - Use
set()to replace an existing element andadd()to insert a new one. - ArrayList is usually a practical choice for general-purpose indexed lists.