Java - ArrayList

Java ArrayList – Detailed Notes

ArrayList in Java 

Java ArrayList is one of the most widely used classes in the Java Collections Framework. It belongs to the java.util package and represents a resizable, dynamic array capable of storing elements of any type. Unlike traditional Java arrays which have a fixed size, ArrayList can automatically grow and shrink as elements are added or removed. Due to its flexibility, performance advantages, and ease of use, ArrayList is frequently chosen for applications where frequent data retrieval and iteration are needed. This document provides an in-depth explanation of ArrayList, its methods, internal structure, performance considerations, examples with code outputs, and best practices. The explanations are written with SEO-rich keywords so this content aligns with common developer queries like β€œJava ArrayList tutorial”, β€œArrayList vs LinkedList”, β€œJava dynamic array”, β€œJava ArrayList example with output”, β€œhow ArrayList works internally”, and β€œJava Collections Framework notes”.

Introduction to Java ArrayList

ArrayList in Java is an implementation of the List interface based on a dynamic array. It stores elements in a contiguous memory structure similar to arrays, but unlike arrays, it can increase its size automatically. ArrayList allows duplicate elements, null values, and maintains insertion order, making it ideal for many real-time programs. As part of the Collections Framework, ArrayList provides various built-in methods for adding, removing, searching, sorting, and iterating data. Being a generic class, ArrayList allows you to create type-safe collections. Developers commonly use ArrayList when the primary operations performed are iteration and random access because both are very efficient. ArrayList is a much preferred data structure due to its simplicity and powerful features. Many interview questions related to Java collections focus on ArrayList because of its internal architecture and performance characteristics. Understanding how ArrayList works internally is essential for writing optimized Java programs.

Basic Example of Using ArrayList

Below is a simple program that demonstrates the basic use of ArrayList in Java. The example includes creating an ArrayList of Strings, adding elements, and printing them. This program helps beginners understand how straightforward it is to use ArrayList compared to regular arrays. The output is also provided to help visualize what the program produces.


import java.util.ArrayList;

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

        names.add("Amit");
        names.add("Ria");
        names.add("Neha");
        names.add("Kiran");

        System.out.println("Names in the ArrayList: " + names);
    }
}

Output:


Names in the ArrayList: [Amit, Ria, Neha, Kiran]

Features of Java ArrayList

ArrayList offers several important features that make it one of the most powerful and flexible data structures in Java. It supports dynamic resizing, meaning that it automatically expands when the internal array becomes full. ArrayList maintains the insertion order, ensuring that elements appear in the same sequence in which they are added. It allows duplicate values, making it suitable for use cases where multiple identical items must be maintained. ArrayList allows random access using an index because internally it uses an array. This makes retrieval operations extremely fast compared to linked lists. Another important feature is that ArrayList implements the Serializable and Cloneable interfaces, allowing objects to be serialized and cloned. Additionally, ArrayList supports iterators, lambda functions, and enhanced for-loops for easy traversal. It is also thread-unsafe by default, which means it performs faster in single-thread environments, giving better performance. For synchronized use, developers can wrap it using Collections.synchronizedList(). These features collectively make ArrayList highly versatile for Java applications.

Example Demonstrating ArrayList Features


import java.util.ArrayList;
import java.util.Collections;

public class ArrayListFeatures {
    public static void main(String[] args) {
        ArrayList numbers = new ArrayList<>();
        numbers.add(50);
        numbers.add(10);
        numbers.add(10); 
        numbers.add(30);

        System.out.println("Original List: " + numbers);

        Collections.sort(numbers);

        System.out.println("Sorted List: " + numbers);
        System.out.println("Element at index 2: " + numbers.get(2));
    }
}

Output:


Original List: [50, 10, 10, 30]
Sorted List: [10, 10, 30, 50]
Element at index 2: 30

Internal Working of ArrayList

Understanding how ArrayList works internally helps developers optimize performance. Internally, ArrayList uses an array called elementData to store elements. When the array becomes full and a new element is added, ArrayList increases its size using a resizing strategy called dynamic array resizing. The new capacity is calculated as 1.5 times the old capacity, meaning ArrayList grows gradually rather than doubling like some other languages do. This resizing process involves creating a new larger array and copying elements from the old array to the new one, which is an expensive operation. Because of this, frequent additions at large scale can impact performance if initial capacity is not set properly. Random access is extremely fast because elements are stored in contiguous memory, making index-based retrieval O(1). Adding elements at the end is usually O(1), but occasionally becomes O(n) when resizing occurs. Removal of elements from the middle is O(n) because elements need to be shifted. Thus, ArrayList is most efficient for read-intensive operations rather than insert-delete heavy tasks. This internal mechanism is important for understanding the difference between ArrayList and LinkedList.

Example Showing Capacity Growth


import java.util.ArrayList;

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

        for (int i = 1; i <= 15; i++) {
            list.add(i);
            System.out.println("Added: " + i + " | Size: " + list.size());
        }
    }
}

Output (sample):


Added: 1 | Size: 1
Added: 2 | Size: 2
...
Added: 15 | Size: 15

Common Methods of ArrayList

ArrayList provides a rich set of methods that make it easy to manipulate data. Some commonly used methods include add(), get(), set(), remove(), size(), contains(), indexOf(), clear(), and isEmpty(). The add() method inserts an element, while get() retrieves elements at a specified index. The set() method replaces an existing element, and remove() deletes elements either by index or by value. contains() helps in searching, while indexOf() returns the position of the first occurrence of an element. The clear() method removes all elements, and size() returns the total number of items currently stored. These methods are designed to simplify development and reduce the need for manual array handling. Understanding these methods is essential for writing efficient and clean Java code.

Example Demonstrating ArrayList Methods


import java.util.ArrayList;

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

        list.add("Java");
        list.add("Python");
        list.add("C++");

        System.out.println("Original List: " + list);

        list.set(1, "JavaScript");
        System.out.println("After set(): " + list);

        list.remove("C++");
        System.out.println("After remove(): " + list);

        System.out.println("Contains Java? " + list.contains("Java"));
        System.out.println("Size: " + list.size());
    }
}

Output:


Original List: [Java, Python, C++]
After set(): [Java, JavaScript, C++]
After remove(): [Java, JavaScript]
Contains Java? true
Size: 2

Iterating Through ArrayList

ArrayList supports several types of iteration techniques including for-loop, enhanced for-loop, iterator, list iterator, and lambda expressions. Iteration is one of the most common operations performed on ArrayList, so choosing the right method can improve readability and performance. The enhanced for-loop is simple and most commonly used for reading elements. The iterator provides methods like hasNext() and next() and supports safe removal during iteration. The ListIterator allows bidirectional iteration. Lambda expressions make iteration more concise and follow functional programming style, especially when used with the forEach() method. Choosing the correct iteration method enhances efficiency and readability.

Example of Different Iteration Techniques


import java.util.ArrayList;
import java.util.Iterator;

public class ArrayListIteration {
    public static void main(String[] args) {
        ArrayList names = new ArrayList<>();
        names.add("Ravi");
        names.add("Meena");
        names.add("Suresh");

        System.out.println("Using Enhanced For-loop:");
        for (String name : names) {
            System.out.println(name);
        }

        System.out.println("\nUsing Iterator:");
        Iterator it = names.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }
}

Output:


Using Enhanced For-loop:
Ravi
Meena
Suresh

Using Iterator:
Ravi
Meena
Suresh


ArrayList is one of the most important and frequently used classes in Java programming. It offers dynamic resizing, easy element manipulation, fast random access, and strong support for iteration techniques. Understanding its internal workings, performance characteristics, and commonly used methods helps developers write optimized, clean, and efficient code. ArrayList is ideal for applications where elements are mostly read or iterated rather than inserted or removed frequently from the middle. Its flexibility, simplicity, and extensive built-in methods make it a preferred choice in real-world Java development. By mastering Java ArrayList, developers strengthen their understanding of the entire Java Collections Framework.

logo

Java

Beginner 5 Hours
Java ArrayList – Detailed Notes

ArrayList in Java 

Java ArrayList is one of the most widely used classes in the Java Collections Framework. It belongs to the java.util package and represents a resizable, dynamic array capable of storing elements of any type. Unlike traditional Java arrays which have a fixed size, ArrayList can automatically grow and shrink as elements are added or removed. Due to its flexibility, performance advantages, and ease of use, ArrayList is frequently chosen for applications where frequent data retrieval and iteration are needed. This document provides an in-depth explanation of ArrayList, its methods, internal structure, performance considerations, examples with code outputs, and best practices. The explanations are written with SEO-rich keywords so this content aligns with common developer queries like “Java ArrayList tutorial”, “ArrayList vs LinkedList”, “Java dynamic array”, “Java ArrayList example with output”, “how ArrayList works internally”, and “Java Collections Framework notes”.

Introduction to Java ArrayList

ArrayList in Java is an implementation of the List interface based on a dynamic array. It stores elements in a contiguous memory structure similar to arrays, but unlike arrays, it can increase its size automatically. ArrayList allows duplicate elements, null values, and maintains insertion order, making it ideal for many real-time programs. As part of the Collections Framework, ArrayList provides various built-in methods for adding, removing, searching, sorting, and iterating data. Being a generic class, ArrayList allows you to create type-safe collections. Developers commonly use ArrayList when the primary operations performed are iteration and random access because both are very efficient. ArrayList is a much preferred data structure due to its simplicity and powerful features. Many interview questions related to Java collections focus on ArrayList because of its internal architecture and performance characteristics. Understanding how ArrayList works internally is essential for writing optimized Java programs.

Basic Example of Using ArrayList

Below is a simple program that demonstrates the basic use of ArrayList in Java. The example includes creating an ArrayList of Strings, adding elements, and printing them. This program helps beginners understand how straightforward it is to use ArrayList compared to regular arrays. The output is also provided to help visualize what the program produces.

import java.util.ArrayList; public class ArrayListExample { public static void main(String[] args) { ArrayList names = new ArrayList<>(); names.add("Amit"); names.add("Ria"); names.add("Neha"); names.add("Kiran"); System.out.println("Names in the ArrayList: " + names); } }

Output:

Names in the ArrayList: [Amit, Ria, Neha, Kiran]

Features of Java ArrayList

ArrayList offers several important features that make it one of the most powerful and flexible data structures in Java. It supports dynamic resizing, meaning that it automatically expands when the internal array becomes full. ArrayList maintains the insertion order, ensuring that elements appear in the same sequence in which they are added. It allows duplicate values, making it suitable for use cases where multiple identical items must be maintained. ArrayList allows random access using an index because internally it uses an array. This makes retrieval operations extremely fast compared to linked lists. Another important feature is that ArrayList implements the Serializable and Cloneable interfaces, allowing objects to be serialized and cloned. Additionally, ArrayList supports iterators, lambda functions, and enhanced for-loops for easy traversal. It is also thread-unsafe by default, which means it performs faster in single-thread environments, giving better performance. For synchronized use, developers can wrap it using Collections.synchronizedList(). These features collectively make ArrayList highly versatile for Java applications.

Example Demonstrating ArrayList Features

import java.util.ArrayList; import java.util.Collections; public class ArrayListFeatures { public static void main(String[] args) { ArrayList numbers = new ArrayList<>(); numbers.add(50); numbers.add(10); numbers.add(10); numbers.add(30); System.out.println("Original List: " + numbers); Collections.sort(numbers); System.out.println("Sorted List: " + numbers); System.out.println("Element at index 2: " + numbers.get(2)); } }

Output:

Original List: [50, 10, 10, 30] Sorted List: [10, 10, 30, 50] Element at index 2: 30

Internal Working of ArrayList

Understanding how ArrayList works internally helps developers optimize performance. Internally, ArrayList uses an array called elementData to store elements. When the array becomes full and a new element is added, ArrayList increases its size using a resizing strategy called dynamic array resizing. The new capacity is calculated as 1.5 times the old capacity, meaning ArrayList grows gradually rather than doubling like some other languages do. This resizing process involves creating a new larger array and copying elements from the old array to the new one, which is an expensive operation. Because of this, frequent additions at large scale can impact performance if initial capacity is not set properly. Random access is extremely fast because elements are stored in contiguous memory, making index-based retrieval O(1). Adding elements at the end is usually O(1), but occasionally becomes O(n) when resizing occurs. Removal of elements from the middle is O(n) because elements need to be shifted. Thus, ArrayList is most efficient for read-intensive operations rather than insert-delete heavy tasks. This internal mechanism is important for understanding the difference between ArrayList and LinkedList.

Example Showing Capacity Growth

import java.util.ArrayList; public class ArrayListCapacity { public static void main(String[] args) { ArrayList list = new ArrayList<>(); for (int i = 1; i <= 15; i++) { list.add(i); System.out.println("Added: " + i + " | Size: " + list.size()); } } }

Output (sample):

Added: 1 | Size: 1 Added: 2 | Size: 2 ... Added: 15 | Size: 15

Common Methods of ArrayList

ArrayList provides a rich set of methods that make it easy to manipulate data. Some commonly used methods include add(), get(), set(), remove(), size(), contains(), indexOf(), clear(), and isEmpty(). The add() method inserts an element, while get() retrieves elements at a specified index. The set() method replaces an existing element, and remove() deletes elements either by index or by value. contains() helps in searching, while indexOf() returns the position of the first occurrence of an element. The clear() method removes all elements, and size() returns the total number of items currently stored. These methods are designed to simplify development and reduce the need for manual array handling. Understanding these methods is essential for writing efficient and clean Java code.

Example Demonstrating ArrayList Methods

import java.util.ArrayList; public class ArrayListMethods { public static void main(String[] args) { ArrayList list = new ArrayList<>(); list.add("Java"); list.add("Python"); list.add("C++"); System.out.println("Original List: " + list); list.set(1, "JavaScript"); System.out.println("After set(): " + list); list.remove("C++"); System.out.println("After remove(): " + list); System.out.println("Contains Java? " + list.contains("Java")); System.out.println("Size: " + list.size()); } }

Output:

Original List: [Java, Python, C++] After set(): [Java, JavaScript, C++] After remove(): [Java, JavaScript] Contains Java? true Size: 2

Iterating Through ArrayList

ArrayList supports several types of iteration techniques including for-loop, enhanced for-loop, iterator, list iterator, and lambda expressions. Iteration is one of the most common operations performed on ArrayList, so choosing the right method can improve readability and performance. The enhanced for-loop is simple and most commonly used for reading elements. The iterator provides methods like hasNext() and next() and supports safe removal during iteration. The ListIterator allows bidirectional iteration. Lambda expressions make iteration more concise and follow functional programming style, especially when used with the forEach() method. Choosing the correct iteration method enhances efficiency and readability.

Example of Different Iteration Techniques

import java.util.ArrayList; import java.util.Iterator; public class ArrayListIteration { public static void main(String[] args) { ArrayList names = new ArrayList<>(); names.add("Ravi"); names.add("Meena"); names.add("Suresh"); System.out.println("Using Enhanced For-loop:"); for (String name : names) { System.out.println(name); } System.out.println("\nUsing Iterator:"); Iterator it = names.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } }

Output:

Using Enhanced For-loop: Ravi Meena Suresh Using Iterator: Ravi Meena Suresh


ArrayList is one of the most important and frequently used classes in Java programming. It offers dynamic resizing, easy element manipulation, fast random access, and strong support for iteration techniques. Understanding its internal workings, performance characteristics, and commonly used methods helps developers write optimized, clean, and efficient code. ArrayList is ideal for applications where elements are mostly read or iterated rather than inserted or removed frequently from the middle. Its flexibility, simplicity, and extensive built-in methods make it a preferred choice in real-world Java development. By mastering Java ArrayList, developers strengthen their understanding of the entire Java Collections Framework.

Related Tutorials

Frequently Asked Questions for Java

Java is known for its key features such as object-oriented programming, platform independence, robust exception handling, multithreading capabilities, and automatic garbage collection.

The Java Development Kit (JDK) is a software development kit used to develop Java applications. The Java Runtime Environment (JRE) provides libraries and other resources to run Java applications, while the Java Virtual Machine (JVM) executes Java bytecode.

Java is a high-level, object-oriented programming language known for its platform independence. This means that Java programs can run on any device that has a Java Virtual Machine (JVM) installed, making it versatile across different operating systems.

Deadlock is a situation in multithreading where two or more threads are blocked forever, waiting for each other to release resources.

Functional programming in Java involves writing code using functions, immutability, and higher-order functions, often utilizing features introduced in Java 8.

A process is an independent program in execution, while a thread is a lightweight subprocess that shares resources with other threads within the same process.

The Comparable interface defines a natural ordering for objects, while the Comparator interface defines an external ordering.

The List interface allows duplicate elements and maintains the order of insertion, while the Set interface does not allow duplicates and does not guarantee any specific order.

String is immutable, meaning its value cannot be changed after creation. StringBuffer and StringBuilder are mutable, allowing modifications to their contents. The main difference between them is that StringBuffer is synchronized, making it thread-safe, while StringBuilder is not.

Checked exceptions are exceptions that must be either caught or declared in the method signature, while unchecked exceptions do not require explicit handling.

ArrayList is backed by a dynamic array, providing fast random access but slower insertions and deletions. LinkedList is backed by a doubly-linked list, offering faster insertions and deletions but slower random access.

Autoboxing is the automatic conversion between primitive types and their corresponding wrapper classes. For example, converting an int to Integer.

The 'synchronized' keyword in Java is used to control access to a method or block of code by multiple threads, ensuring that only one thread can execute it at a time.

Multithreading in Java allows concurrent execution of two or more threads, enabling efficient CPU utilization and improved application performance.

A HashMap is a collection class that implements the Map interface, storing key-value pairs. It allows null values and keys and provides constant-time performance for basic operations.

Java achieves platform independence by compiling source code into bytecode, which is executed by the JVM. This allows Java programs to run on any platform that has a compatible JVM.

The Serializable interface provides a default mechanism for serialization, while the Externalizable interface allows for custom serialization behavior.

The 'volatile' keyword in Java indicates that a variable's value will be modified by multiple threads, ensuring that the most up-to-date value is always visible.

Serialization is the process of converting an object into a byte stream, enabling it to be saved to a file or transmitted over a network.

The finalize() method is called by the garbage collector before an object is destroyed, allowing for cleanup operations.

The 'final' keyword in Java is used to define constants, prevent method overriding, and prevent inheritance of classes, ensuring that certain elements remain unchanged.

Garbage collection is the process by which the JVM automatically deletes objects that are no longer reachable, freeing up memory resources.

'throw' is used to explicitly throw an exception, while 'throws' is used in method declarations to specify that a method can throw one or more exceptions.

The 'super' keyword in Java refers to the immediate parent class and is used to access parent class methods, constructors, and variables.

The JVM is responsible for loading, verifying, and executing Java bytecode. It provides an abstraction between the compiled Java program and the underlying hardware, enabling platform independence.

line

Copyrights © 2024 letsupdateskills All rights reserved