ArrayList in Java – Complete Guide for Developers

Introduction

In Java, ArrayList is a part of the Collection Framework and is present in the java.util package. It is a resizable array implementation of the List interface. Unlike arrays, which have a fixed size, an ArrayList can dynamically grow or shrink as elements are added or removed.

1. Key Features of ArrayList

  1. Dynamic Resizing – Automatically grows when elements exceed capacity and shrinks when elements are removed.
  2. Indexed Access – Provides fast random access using an index (similar to arrays).
  3. Duplicates Allowed – Stores duplicate elements as well as null values.
  4. Maintains Insertion Order – Elements are stored in the order they are inserted.
  5. Non-synchronized – Not thread-safe by default, but can be synchronized using Collections.synchronizedList().
  6. Implements List Interface – Supports all list operations like insertion, deletion, traversal, and searching.
  7. Heterogeneous Data – Technically possible (when using raw types), but not recommended. Best practice is to use generics.

2. Syntax of ArrayList in Java

To declare and initialize an ArrayList, you can use the following syntax:

// Creating an ArrayList of Integer type
ArrayList < Integer > arr = new ArrayList < Integer > ();
  • ArrayList<Integer> specifies that this list will store only Integer values.
  • new ArrayList<Integer>() creates a new empty ArrayList.

👉You can also create an ArrayList with other data types using generics:

ArrayList < String > names = new ArrayList < String > (); // Stores String values
ArrayList < Double > prices = new ArrayList < Double > (); // Stores Double values
ArrayList < Character > letters = new ArrayList < >(); // Diamond operator, type inferred

Note:

  • Since Java 7, you can use the diamond operator <> to avoid repeating the type on the right-hand side:
ArrayList<Integer> numbers = new ArrayList<>(); // Type is inferred as Integer
  • Generics enforce type safety, preventing accidental insertion of wrong types.

3. Declaration and Initialization

import java.util.ArrayList;

public class ArrayListExample {
    public static void main(String[] args) {
        // Creating an ArrayList of String type
        ArrayList<String> fruits = new ArrayList<>();

        // Adding elements
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Mango");
        fruits.add("Orange");

        System.out.println(fruits);
    }
}

Output:

[Apple, Banana, Mango, Orange]

4. Common Operations on ArrayList

The ArrayList class provides many useful methods to perform operations. Let’s look at the most commonly used ones with description and examples:

4.a. Adding Elements

  • The add() method is used to insert elements into the ArrayList.
  • You can add elements at the end or at a specific index.
ArrayList < String > fruits = new ArrayList < >();

fruits.add("Apple"); // Adds element at the end
fruits.add("Banana");
fruits.add(1, "Mango"); // Adds "Mango" at index 1
System.out.println(fruits);

Output:

[Apple, Mango, Banana]

4.b. Accessing Elements

  • The get(int index) method returns the element present at the given index.
  • Index starts from 0.
String fruit = fruits.get(1);
System.out.println("Element at index 1: " + fruit);

Output:

Element at index 1: Mango

4.c. Updating Elements

  • The set(int index, E element) method replaces the element at the specified index with a new value.
fruits.set(1, "Orange");   // Replaces "Mango" with "Orange"
System.out.println(fruits);

Output:

[Apple, Orange, Banana]

4.d. Removing Elements

  • The remove() method deletes elements by value or by index.
fruits.remove("Banana");   // Removes "Banana"
fruits.remove(0);          // Removes element at index 0
System.out.println(fruits);

Output:

[Orange]

4.e. Checking Size

  • The size() method returns the total number of elements in the list.
System.out.println("Size: " + fruits.size());

4.f. Iterating Over ArrayList

  • There are multiple ways to iterate over an ArrayList:
// Using for-each loop
for (String f : fruits) {
    System.out.println(f);
}

// Using for loop with index
for (int i = 0; i < fruits.size(); i++) {
    System.out.println(fruits.get(i));
}

// Using forEach() method with lambda
fruits.forEach(System.out::println);

4.g. Checking if Element Exists

  • The contains(Object o) method returns true if the element exists, otherwise false.
if (fruits.contains("Mango")) {
    System.out.println("Mango is in the list!");
}

4.h. Converting ArrayList to Array

  • The toArray() method converts an ArrayList into a normal array.
String[] arr = fruits.toArray(new String[0]);
for (String s : arr) {
    System.out.println(s);
}

Example – Full Program

import java.util.ArrayList;

public class ArrayListDemo {
    public static void main(String[] args) {
        ArrayList<String> fruits = new ArrayList<>();

        // Adding elements
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Mango");
        fruits.add("Orange");

        // Displaying ArrayList
        System.out.println("Fruits: " + fruits);

        // Accessing elements
        System.out.println("Element at index 1: " + fruits.get(1));

        // Updating element
        fruits.set(2, "Papaya");
        System.out.println("Updated Fruits: " + fruits);

        // Removing element
        fruits.remove("Orange");
        System.out.println("After removal: " + fruits);

        // Iterating
        System.out.println("Iterating with for-each loop:");
        for (String fruit : fruits) {
            System.out.println(fruit);
        }

        // Size of ArrayList
        System.out.println("Total Fruits: " + fruits.size());
    }
}

Output:

Fruits: [Apple, Banana, Mango, Orange]
Element at index 1: Banana
Updated Fruits: [Apple, Banana, Papaya, Orange]
After removal: [Apple, Banana, Papaya]
Iterating with for-each loop:
Apple
Banana
Papaya
Total Fruits: 3

5. When to Use ArrayList in Java

ArrayList is one of the most commonly used collection classes in Java, but it is not always the best choice for every scenario. Here’s when you should use it:

5.a. When You Need Dynamic Arrays

  • Unlike standard arrays in Java, the size of an ArrayList can grow or shrink automatically.
  • Use ArrayList when you don’t know the number of elements in advance.

Example:

ArrayList < String > names = new ArrayList < >();
names.add("Alice");
names.add("Bob"); // size grows automatically

5.b. When You Need Fast Random Access

  • ArrayList provides O(1) time complexity for accessing elements by index because it is internally backed by an array.
  • Ideal when your application frequently retrieves elements by index.

Example:

String name = names.get(0); // Fast access

5.c. When Insertion/Deletion is Mostly at the End

  • Adding elements to the end of the list is very efficient (O(1) amortized).
  • Removing or inserting elements in the middle or beginning is slower (O(n)), so avoid if frequent mid-list modifications are required.

Example:

names.add("Charlie"); // Efficient
names.remove(names.size() - 1); // Efficient

5.d. When You Want to Maintain Order

  • ArrayList maintains insertion order, which means elements are stored in the order they were added.
  • Useful when order matters in your application.

Example:

ArrayList < String > tasks = new ArrayList < >();
tasks.add("Design");
tasks.add("Development");
tasks.add("Testing");
System.out.println(tasks); // [Design, Development, Testing]

5.e. When You Need Null or Duplicate Values

  • ArrayList allows duplicate elements and null values, unlike Set implementations.

Example:

ArrayList < String > list = new ArrayList < >();
list.add(null);
list.add("Apple");
list.add("Apple"); // Duplicates allowed

✅ When Not to Use ArrayList

  • Frequent insertions/deletions in the middle or start → Use LinkedList instead.
  • Thread-safe operations required → Use CopyOnWriteArrayList or Collections.synchronizedList().
  • Primitive types → Consider using arrays or IntStream/long[] for performance, as ArrayList<Integer> introduces boxing/unboxing overhead.

In short:

Use ArrayList when you need a dynamic, ordered, and index-based collection where additions/removals are mostly at the end, and you may allow duplicates and nulls.

6. ArrayList Complexity

ArrayList is backed by a dynamic array, so operations are indexed-based.

OperationComplexityNotes
Access (get/set)O(1)Direct index access.
Insert at endO(1) amortizedMay require resizing (O(n) occasionally).
Insert at indexO(n)Shifts elements to the right.
Remove by indexO(n)Shifts elements to the left.
Remove by valueO(n)Needs traversal.
Search (contains, indexOf)O(n)Linear search.
IterationO(n)Sequential traversal.

👉 For a detailed guide on initializing an ArrayList using List.of() and Arrays.asList(), check out How to Initialize ArrayList in Java

🎯Conclusion

The ArrayList in Java is a powerful and flexible alternative to arrays, especially when you need dynamic resizing, indexed access, and frequent insertions/deletions. However, if thread-safety is required, you should consider using Collections.synchronizedList() or CopyOnWriteArrayList.

Backend developer working with Java, Spring Boot, Microservices, NoSQL, and AWS. I love sharing knowledge, practical tips, and clean code practices to help others build scalable applications.

Leave a Reply

Your email address will not be published. Required fields are marked *