import java.util.ArrayList;
ArrayList<String> names = new ArrayList<>();
names.add("Rahul");
names.add("Priya");
names.add("Amit");
System.out.println(names);Java ArrayList: Dynamic Arrays, Operations, and Performance
Direct Answer & Core Concept
ArrayList is one of the most commonly used collection classes in Java. It provides a resizable array that can grow or shrink automatically as elements are added or removed.
Unlike a normal Java array, an ArrayList does not require you to decide its size when creating it. You can add elements dynamically and access them using an index.
For beginners, ArrayList is often the best starting point when you need an ordered collection that allows duplicate values.
Detailed Explanation & Mechanics
What Is ArrayList in Java?
ArrayList is a class in the java.util package that implements the List interface.
It stores elements in an internal array-like structure and automatically manages its capacity as the collection grows.
Output:
[Rahul, Priya, Amit]The important point is that you do not need to specify how many elements the list will contain.
ArrayList Syntax
The basic syntax is:
ArrayList<Type> listName = new ArrayList<>();For example:
ArrayList<String> cities = new ArrayList<>();An integer list can be created using:
ArrayList<Integer> numbers = new ArrayList<>();A list of custom objects can also be created:
ArrayList<Student> students = new ArrayList<>();Java generics specify the type of objects that the ArrayList should contain.
Importing ArrayList
Because ArrayList belongs to the java.util package, you normally import it before using it.
import java.util.ArrayList;You can also import several collection classes with:
import java.util.*;For production code, importing the specific class is often clearer.
Creating an ArrayList
The simplest way to create an ArrayList is:
ArrayList<String> fruits = new ArrayList<>();You can then add values:
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Mango");The list now contains three elements.
System.out.println(fruits);Output:
[Apple, Banana, Mango]ArrayList with Initial Capacity
You can optionally provide an initial capacity.
ArrayList<String> names = new ArrayList<>(20);This does not mean the list already contains 20 elements.
It means the internal storage can initially accommodate approximately that many elements before additional capacity management is needed.
For example:
ArrayList<Integer> numbers = new ArrayList<>(100);The list is still empty:
System.out.println(numbers.size());Output:
Adding Elements to ArrayList
The add() method adds an element to the end of the list.
ArrayList<String> colors = new ArrayList<>();
colors.add("Red");
colors.add("Green");
colors.add("Blue");
System.out.println(colors);Output:
[Red, Green, Blue]Adding an Element at a Specific Index
You can insert an element at a particular position using:
add(index, element)Example:
ArrayList<String> languages = new ArrayList<>();
languages.add("Java");
languages.add("Python");
languages.add("C++");
languages.add(1, "JavaScript");
System.out.println(languages);Output:
[Java, JavaScript, Python, C++]Elements after the specified position are shifted to make room for the new element.
Accessing ArrayList Elements
Use the get() method to retrieve an element.
ArrayList<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Mango");
System.out.println(fruits.get(1));Output:
BananaArrayList indexes start at 0.
Therefore:
Index 0 → AppleIndex 1 → BananaIndex 2 → MangoUpdating an ArrayList Element
The set() method replaces an existing element.
ArrayList<String> names = new ArrayList<>();
names.add("Amit");
names.add("Rahul");
names.add("Priya");
names.set(1, "Rohan");
System.out.println(names);Output:
[Amit, Rohan, Priya]Unlike add(), set() does not increase the size of the list.
Removing Elements from ArrayList
You can remove elements by index.
ArrayList<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Mango");
fruits.remove(1);
System.out.println(fruits);Output:
[Apple, Mango]You can also remove an element by value:
fruits.remove("Apple");This removes the first matching element.
Important: remove() with Integer
When using ArrayList<Integer>, be careful because remove() has both index-based and object-based behavior.
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);
numbers.add(30);This:
numbers.remove(1);removes the element at index 1.
Result:
[10, 30]But this:
numbers.remove(Integer.valueOf(20));removes the value 20.
This distinction is important when working with integer lists.
Finding the Size of an ArrayList
Use the size() method.
ArrayList<String> names = new ArrayList<>();
names.add("Amit");
names.add("Rahul");
names.add("Priya");
System.out.println(names.size());Output:
3Remember that size() returns the number of elements currently stored in the list.
It is different from the internal capacity of the ArrayList.
Checking Whether an ArrayList Is Empty
Use:
isEmpty()Example:
ArrayList<String> names = new ArrayList<>();
System.out.println(names.isEmpty());Output:
trueAfter adding an element:
names.add("Amit");
System.out.println(names.isEmpty());Output:
falseChecking Whether an ArrayList Contains an Element
Use:
contains()Example:
ArrayList<String> languages = new ArrayList<>();
languages.add("Java");
languages.add("Python");
languages.add("C++");
System.out.println(languages.contains("Java"));Output:
trueIf the element does not exist:
System.out.println(languages.contains("PHP"));Output:
falseFinding an Element's Index
Use indexOf():
ArrayList<String> names = new ArrayList<>();
names.add("Amit");
names.add("Rahul");
names.add("Priya");
System.out.println(names.indexOf("Rahul"));Output:
1If the element is not found, indexOf() returns:
-1For duplicate elements, indexOf() returns the index of the first matching element.
Finding the Last Occurrence
Use:
lastIndexOf()Example:
ArrayList<String> names = new ArrayList<>();
names.add("Amit");
names.add("Rahul");
names.add("Amit");
System.out.println(names.lastIndexOf("Amit"));Output:
2Iterating Through an ArrayList
There are several ways to loop through an ArrayList.
Traditional for Loop
ArrayList<String> names = new ArrayList<>();
names.add("Amit");
names.add("Rahul");
names.add("Priya");
for (int i = 0;
i < names.size();
i++) {
System.out.println(names.get(i));
}This approach is useful when you need the index.
Enhanced for Loop
for (String name : names) {
System.out.println(name);
}This is usually simpler when you only need the values.
forEach()
You can also use:
names.forEach(name -> System.out.println(name));This uses a lambda expression.
Iterator
An Iterator can be used when you need controlled traversal and safe removal during iteration.
import java.util.ArrayList;
import java.util.Iterator;
ArrayList<String> names = new ArrayList<>();
names.add("Amit");
names.add("Rahul");
names.add("Priya");
Iterator<String> iterator = names.iterator();
while (iterator.hasNext()) {
String name = iterator.next();
System.out.println(name);
}Removing Elements While Iterating
Directly modifying an ArrayList during an enhanced for loop can cause a ConcurrentModificationException.
Avoid:
for (String name : names) {
if (name.equals("Rahul")) {
names.remove(name);
}
}Instead, use an Iterator:
Iterator<String> iterator = names.iterator();
while (iterator.hasNext()) {
String name = iterator.next();
if (name.equals("Rahul")) {
iterator.remove();
}
}This is the appropriate iterator-based removal pattern.
Sorting an ArrayList
You can sort a list using Collections.sort().
import java.util.ArrayList;
import java.util.Collections;
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(50);
numbers.add(10);
numbers.add(30);
numbers.add(20);
Collections.sort(numbers);
System.out.println(numbers);Output:
[10, 20, 30, 50]Modern Java also supports:
numbers.sort(null);For custom sorting, a Comparator can be supplied.
numbers.sort((a, b) -> b - a);For integer subtraction-based comparators, Integer.compare(b, a) is safer in general:
numbers.sort((a, b) -> Integer.compare(b, a));Reversing an ArrayList
Use:
Collections.reverse(list);Example:
ArrayList<String> names = new ArrayList<>();
names.add("Amit");
names.add("Rahul");
names.add("Priya");
Collections.reverse(names);
System.out.println(names);Output:
[Priya, Rahul, Amit]Clearing an ArrayList
The clear() method removes all elements.
ArrayList<String> names = new ArrayList<>();
names.add("Amit");
names.add("Rahul");
names.clear();
System.out.println(names);Output:
[]After clear(), the list contains no elements.
ArrayList Allows Duplicate Values
An ArrayList can contain the same value multiple times.
ArrayList<String> names = new ArrayList<>();
names.add("Amit");
names.add("Rahul");
names.add("Amit");
System.out.println(names);Output:
[Amit, Rahul, Amit]This makes ArrayList useful when duplicate entries are meaningful.
ArrayList Maintains Insertion Order
Elements are normally returned in their list order.
ArrayList<String> languages = new ArrayList<>();
languages.add("Java");
languages.add("Python");
languages.add("C++");
System.out.println(languages);Output:
[Java, Python, C++]The list maintains the sequence in which elements were inserted unless you explicitly modify that ordering.
ArrayList and Null Values
ArrayList can contain null values.
ArrayList<String> names = new ArrayList<>();
names.add("Amit");
names.add(null);
names.add("Rahul");
System.out.println(names);Output:
[Amit, null, Rahul]Whether null is appropriate depends on the application.
ArrayList and Primitive Types
Java collections store objects rather than primitive types.
Therefore, you cannot directly write:
ArrayList<int> numbers;Instead, use the wrapper class:
ArrayList<Integer> numbers = new ArrayList<>();Java's autoboxing automatically converts:
intto:
Integerwhen necessary.
Example:
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);
numbers.add(30);ArrayList with Custom Objects
ArrayList becomes particularly useful when storing objects.
class Student {
String name;
int age;
Student(String name, int age) {
this.name = name;
this.age = age;
}
}You can create a list:
ArrayList<Student> students = new ArrayList<>();
students.add(new Student("Amit", 20));
students.add(new Student("Priya", 21));You can then access the objects:
for (Student student : students) {
System.out.println(student.name);
}This pattern is common in real Java applications.
ArrayList Performance
Understanding performance is important when choosing between Java collection types.
A simplified performance overview is:
| Operation | Typical Complexity |
|---|---|
get(index) | O(1) |
set(index, value) | O(1) |
| Add at end | Amortized O(1) |
| Add at middle | O(n) |
| Remove at end | O(1) |
| Remove from middle | O(n) |
Search with contains() | O(n) |
indexOf() | O(n) |
| Sorting | O(n log n) typically |
These are typical complexity characteristics rather than guarantees for every possible implementation detail.
Why get() Is Fast
ArrayList uses an array-based storage structure.
Because array elements can be accessed directly by index, this operation is typically constant time:
String name = names.get(500);The list does not need to scan all previous elements to find index 500.
This is one of the major advantages of ArrayList.
Why Inserting in the Middle Is Slower
Suppose a list contains:
[A, B, C, D, E]If you insert X at index 2:
list.add(2, "X");the elements after that position need to be shifted:
[A, B, X, C, D, E]As the list becomes larger, more elements may need to move.
Therefore, insertion in the middle is typically O(n).
Why Removing from the Middle Is Slower
Consider:
[A, B, C, D, E]Removing C requires later elements to shift:
[A, B, D, E]Therefore, removing an element from the middle is typically O(n).
ArrayList Dynamic Resizing
One of the biggest differences between an ordinary array and an ArrayList is automatic capacity management.
Consider:
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);
numbers.add(30);You did not specify the final size.
When the internal storage becomes insufficient, the implementation can allocate a larger backing array and copy existing elements into it.
This allows the list to grow dynamically.
The exact resizing strategy is an implementation detail and should not be relied on as a fixed API rule.
Size vs Capacity
These two concepts are different.
Size means the number of elements currently stored.
numbers.size();Capacity refers to how much internal storage is currently available before another resize may be required.
For example, conceptually:
Size = 5 elementsCapacity = enough internal storage for more elementsThe capacity is not the same thing as the list's logical size.
ArrayList Initial Capacity
If you know approximately how many elements will be added, specifying an initial capacity can reduce some resizing and copying.
ArrayList<String> users = new ArrayList<>(10000);This can be useful when creating a large list and the expected size is reasonably predictable.
However, setting a huge capacity without reason can waste memory.
ArrayList vs Array
Both arrays and ArrayList can store multiple values, but they serve different purposes.
| Feature | Array | ArrayList |
|---|---|---|
| Size | Fixed | Dynamically resizable |
| Syntax | int[] | ArrayList<Integer> |
| Primitive support | Yes | Through wrapper types |
add() method | No | Yes |
remove() method | No | Yes |
get() method | No | Yes |
| Part of Collections Framework | No | Yes |
| Built-in size method | length | size() |
Example array:
int[] numbers = new int[5];Example ArrayList:
ArrayList<Integer> numbers = new ArrayList<>();ArrayList vs LinkedList
Both implement the List interface, but their underlying structures differ.
| Feature | ArrayList | LinkedList |
|---|---|---|
| Main structure | Resizable array | Linked nodes |
| Indexed access | Fast | Slower |
| Random access | Good | Poor |
| Memory overhead | Generally lower | Generally higher |
| Add at end | Efficient | Efficient |
| Middle insertion | Requires shifting | Can be efficient after reaching the location |
| Typical default choice for lists | Often | Less often |
Do not assume that LinkedList is automatically faster whenever you insert or remove elements. In real applications, the cost of locating the position, memory usage, CPU cache behavior, and workload all matter.
For many ordinary list use cases, ArrayList is the practical default.
ArrayList vs Vector
Vector is an older collection class.
ArrayList is generally preferred for modern single-threaded collection usage.
If multiple threads need shared mutable data, choosing a collection should depend on the actual concurrency requirements rather than simply replacing ArrayList with Vector.
Making an ArrayList Unmodifiable
Modern Java provides convenient factory methods such as:
List<String> names = List.of("Amit", "Rahul", "Priya");This creates an unmodifiable list.
Attempting:
names.add("Rohan");will result in an UnsupportedOperationException.
This is different from a normal mutable ArrayList.
Converting ArrayList to Array
You can convert a list into an array using toArray().
ArrayList<String> names = new ArrayList<>();
names.add("Amit");
names.add("Rahul");
names.add("Priya");
String[] array = names.toArray(new String[0]);Now array contains the list elements.
Converting an Array to ArrayList
For example:
String[] names = {
"Amit", "Rahul", "Priya"
};
ArrayList<String> list = new ArrayList<>(Arrays.asList(names));The resulting ArrayList is mutable.
For modern Java, another option is:
ArrayList<String> list = new ArrayList<>(List.of("Amit", "Rahul", "Priya"));Copying an ArrayList
You can create a new mutable list from an existing list:
ArrayList<String> original = new ArrayList<>();
original.add("Java");
original.add("Python");
ArrayList<String> copy = new ArrayList<>(original);The new list contains the same element references.
For objects, this is generally a shallow copy rather than a deep copy.
Passing ArrayList to a Method
An ArrayList can be passed to a method like any other object.
static void printNames(ArrayList<String> names) {
for (String name : names) {
System.out.println(name);
}
}Call it with:
printNames(names);A more flexible design is often to accept the interface:
static void printNames(List<String> names) {
for (String name : names) {
System.out.println(name);
}
}This allows callers to provide other List implementations too.
Returning an ArrayList from a Method
A method can return an ArrayList.
static ArrayList<String> createNames() {
ArrayList<String> names = new ArrayList<>();
names.add("Amit");
names.add("Rahul");
names.add("Priya");
return names;
}However, returning the more general interface can make the API more flexible:
static List<String> createNames() {
return new ArrayList<>(List.of("Amit", "Rahul", "Priya"));
}Generic ArrayList
Generics provide compile-time type safety.
ArrayList<String> names = new ArrayList<>();Now the compiler expects String values.
This is valid:
names.add("Amit");This is not:
names.add(100);Generics reduce accidental type errors and remove the need for many explicit casts.
ArrayList with Streams
ArrayList works naturally with the Java Stream API.
Example:
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);
numbers.add(30);
numbers.add(40);
numbers.stream() .filter(n -> n > 20) .forEach(System.out::println);Output:
3040Streams are useful for expressing collection-processing operations such as filtering, mapping, and aggregation.
Common ArrayList Mistakes
Mistake 1: Using an Invalid Index
This causes:
IndexOutOfBoundsExceptionExample:
ArrayList<String> names = new ArrayList<>();
names.add("Amit");
System.out.println(names.get(1));Only index 0 exists.
Mistake 2: Confusing Size and Capacity
Creating:
new ArrayList<>(100);does not create 100 elements.
The list is still empty:
System.out.println(list.size());Output:
Mistake 3: Removing During Enhanced for Loop
Avoid modifying the list directly inside an enhanced for loop.
Use an Iterator, removeIf(), or another suitable approach.
For example:
names.removeIf(name -> name.equals("Rahul"));Mistake 4: Using ArrayList for Every Problem
ArrayList is excellent for many list-based workloads, but it is not the correct data structure for every situation.
Depending on the problem, you may need:
HashSetfor unique valuesHashMapfor key-value lookupArrayDequefor queue or stack behaviorTreeSetfor sorted unique valuesTreeMapfor sorted key-value data
The correct collection depends on the operations your application performs most frequently.
Best Practices for ArrayList
1. Program to the List interface
Prefer:
List<String> names = new ArrayList<>();instead of unnecessarily exposing:
ArrayList<String> names = new ArrayList<>();The interface-based approach gives you more implementation flexibility.
2. Specify the generic type
Prefer:
ArrayList<String> names = new ArrayList<>();Avoid raw types such as:
ArrayList names = new ArrayList();3. Use initial capacity when useful
If you know a large approximate size:
List<User> users = new ArrayList<>(10000);This may reduce repeated resizing.
4. Use ArrayDeque for stack/queue workloads
Do not automatically use ArrayList as a stack or queue. Deque implementations are usually better suited to those operations.
5. Avoid unnecessary conversions
If your application already uses a List, avoid repeatedly converting it to arrays or other collection types without a reason.
Complete ArrayList Example
Here is a small program demonstrating several common operations:
import java.util.ArrayList;
import java.util.Collections;
public class Main {
public static void main(String[] args) {
ArrayList<String> fruits = new ArrayList<>();
// Add elements
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Mango");
// Add at an index
fruits.add(1, "Orange");
// Access
System.out.println("First fruit: " + fruits.get(0));
// Update
fruits.set(0, "Grapes");
// Check
System.out.println("Contains Mango: " + fruits.contains("Mango"));
// Remove
fruits.remove("Orange");
// Sort
Collections.sort(fruits);
// Display
System.out.println("Fruits: " + fruits);
// Size
System.out.println("Size: " + fruits.size());
}
}Possible output:
First fruit: AppleContains Mango: trueFruits:[Banana, Grapes, Mango]Size: 3When Should You Use ArrayList?
ArrayList is a strong choice when:
You need a dynamically sized list.
You frequently access elements by index.
You want to preserve list order.
Duplicate values are allowed.
You frequently add elements near the end.
You want a straightforward general-purpose
List.
For example:
List<String> products = new ArrayList<>();is a natural choice for storing an ordered collection of products.
When Should You Avoid ArrayList?
Consider another collection when:
You primarily need unique values →
SetYou need key-value relationships →
MapYou need efficient queue/deque operations →
DequeYou need sorted unique values →
TreeSetYou need sorted key-value data →
TreeMapYou need specialized concurrent behavior → appropriate concurrent collection
Choosing a collection based on required operations is more important than simply choosing the most familiar class.
ArrayList Quick Revision
| Concept | Key Point |
|---|---|
| Package | java.util |
| Interface | List |
| Storage | Resizable array-based structure |
| Duplicates | Allowed |
null | Allowed |
| Indexing | Zero-based |
| Random access | Typically O(1) |
| Add at end | Amortized O(1) |
| Middle insertion | Typically O(n) |
| Middle removal | Typically O(n) |
| Search | Typically O(n) |
| Sorting | Typically O(n log n) |
| Primitive types | Use wrapper classes |
| Thread safety | Not synchronized by default |
Frequently Asked Questions
Is ArrayList a dynamic array in Java?
Yes. ArrayList provides a resizable, array-backed list abstraction. It automatically manages its internal storage as elements are added.
Does ArrayList allow duplicates?
Yes. An ArrayList can contain duplicate elements.
Does ArrayList maintain insertion order?
Yes. A normal ArrayList maintains the sequence of elements in the list unless you explicitly modify that order.
Is ArrayList synchronized?
No. ArrayList is not synchronized by default. If multiple threads share and modify a list, choose a concurrency strategy appropriate to the application.
What is the default size of an ArrayList?
The logical size of a newly created ArrayList is 0. Its internal capacity is an implementation detail and should not be confused with size().
Why is ArrayList faster for get()?
Because it uses array-based indexed storage, accessing an element by index is typically O(1).
Can ArrayList store primitive data types?
No. Collections store objects, so wrapper types such as Integer, Double, and Character are used. Autoboxing makes primitive values convenient to add.
What happens when ArrayList becomes full?
Its internal storage can be expanded by allocating a larger backing array and copying existing elements. The exact growth policy is implementation-dependent.
Which is better, ArrayList or LinkedList?
There is no universal winner. For many general-purpose list workloads, ArrayList is a good default, especially when indexed access is important. The appropriate choice depends on the operations and workload.
Can ArrayList contain null?
Yes. An ArrayList can contain null elements.
Graphics and Design Ideas
1. ArrayList vs Array Diagram
Create a side-by-side visual showing:
Java Array[10][20][30][40] Fixed SizeArrayList[10][20][30] → add(40) →[10][20][30][40] Dynamic Growth2. ArrayList Index Diagram
Show:
Index: 0 1 2 3 +--------+--------+--------+--------+ | Apple | Banana | Mango | Orange | +--------+--------+--------+--------+This makes zero-based indexing immediately understandable.
3. ArrayList Performance Graphic
Create a visual table:
get(index) → O(1) FASTset(index, value) → O(1) FASTadd(end) → O(1)* FASTsearch → O(n) LINEARinsert(middle) → O(n) SHIFTINGremove(middle) → O(n) SHIFTINGAdd a small note that add(end) is amortized O(1).
4. Dynamic Resizing Animation
Show:
Small Storage[ A][ B][ C]↓resizeLarger Storage[ A][ B][ C][][]Explain visually that resizing may involve creating larger storage and copying existing elements.
5. ArrayList Method Cheat Sheet
Create an infographic containing:
add() → Addget() → Readset() → Updateremove() → Deletecontains() → Searchsize() → Countclear() → Remove allisEmpty() → Check emptyThese visuals can make the tutorial easier for beginners to scan and understand.
Runnable Code Example: Java ArrayList
Java 17+import java.util.ArrayList;
import java.util.List;
public class ArrayListDemo {
public static void main(String[] args) {
List<String> frameworkList = new ArrayList<>();
frameworkList.add("Spring Boot");
frameworkList.add("Quarkus");
frameworkList.add("Micronaut");
frameworkList.remove("Quarkus");
System.out.println("Frameworks count: " + frameworkList.size());
System.out.println("First Framework: " + frameworkList.get(0));
}
}