Java lists are an essential part of the Java Collections Framework (JCF). They are an ordered collection of elements that help organize sequential data efficiently.
Lists are ideal when element order, indexing, and quick access matter. They have various implementations and flexible options to manage data depending on application requirements.
This guide will explain what the Java List
interface is and how to use it through practical examples.

Prerequisites
- A Java Development Kit (JDK) installed (JDK 8+ preferable).
- A Java IDE or text editor for writing and compiling Java code.
Note: To install Java, follow one of our guides for your operating system:
What Is Java List?
A list in Java is an ordered collection (or sequence) that maintains insertion order. Each element in a list has an index, allowing positional access and manipulation. Lists use indexes to add, retrieve, update, or remove elements. They automatically resize based on the number of elements.
Lists store objects of any type. They also allow duplicate and multiple null elements, making them suitable for cases with repeated or absent values.
The example below shows a list of String objects with duplicate elements:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>(); // creates list
list.add("Alice"); // adds an element
list.add("Bob");
list.add("Alice"); // adds a duplicate element
System.out.println(list); // prints list
}
}
A list typically represents data sequences, such as logs, shopping cart items, or to-do lists.
Java List vs. Java Set
Both List
and Set
are part of the JCF and extend the Collection
interface. However, their behavior and purposes differ.
The table below summarizes the key distinctions between the two data structures:
Feature | List | Set |
---|---|---|
Duplicate elements | Allows duplicate elements. | Does not allow duplicate elements. |
Null elements | Allows multiple null values. | Allows at most one null value (depending on the implementation). |
Order | Maintains insertion order. | Order not guaranteed (unless using TreeSet or LinkedHashSet ). |
Access | Indexed access. | No indexed access. |
Implementations | ArrayList LinkedList Vector Stack | HashSet LinkedHashSet TreeSet |
Java List Class Diagram
The following class diagram shows the class inheritance for Java lists:
The List
interface is part of the java.util
package and extends the Collection
interface. Java has several implementations (classes) of the List
interface, each optimized for a specific use case.
Java List Operations
Lists support various operations, including adding, updating, searching, and removing elements. The examples below use an ArrayList
:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
System.out.println(list);
}
}
The code returns an empty list. The sections below show the basic available operations on lists using this example ArrayList
.
Adding Elements
Use the add(element)
method to append an item to a list:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Alice"); // appends item
System.out.println(list);
}
}
To insert at a specific location, provide the index before the element:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Alice");
list.add(0, "Bob"); // inserts item at position 1
System.out.println(list);
}
}
It inserts the item as the first element (index 0).
Updating Elements
To modify an element in a list, use the set(index, element)
method:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Alice");
list.add("Bob");
System.out.println("Initial list: " + list);
list.set(0, "Alice"); // sets item at position 1
System.out.println("Updated list: " + list);
}
}
The code updates the list's first element (at index 0).
Searching for Elements
To find the index of an element, use indexOf(element)
to find the first occurrence or lastIndexOf(element)
to find the last occurrence of an element.
For example:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Alice");
list.add("Bob");
list.add("Alice");
System.out.println(list);
System.out.println("First Alice is at index: " + list.indexOf("Alice"));
System.out.println("Last Alice is at index: " + list.lastIndexOf("Alice"));
}
}
The methods return different values for the index.
Removing Elements
Remove an element by index using remove(index)
:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Alice");
list.add("Bob");
list.add("Alice");
System.out.println("Initial list: " + list);
list.remove(0);
System.out.println("Updated list: " + list);
}
}
Or remove a specific object with remove(element)
:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Alice");
list.add("Bob");
list.add("Alice");
System.out.println("Initial list: " + list);
list.remove("Alice");
System.out.println("Updated list: " + list);
}
}
It removes the first occurrence of the object.
Accessing Elements
To retrieve an element from a list, use get(index)
. For example:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Alice");
list.add("Bob");
list.add("Alice");
System.out.println("The list is: " + list);
System.out.println("The second element is: " + list.get(1));
}
}
The example returns the second element in the list.
Checking if an Element Is Present
To check if an element is in a list, use the contains(element)
operation:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Alice");
list.add("Bob");
list.add("Alice");
System.out.println("Is Charlie on the list? " + list.contains("Charlie"));
System.out.println("How about Bob? " + list.contains("Bob"));
}
}
The method returns false
if the element is absent, and true
if it is present.
Java List Methods
The List
interface defines methods to perform common operations. The previous sections showed examples of how these methods work on Strings, but the methods are generic and work with any object type.
The table below describes Java List
methods:
Method | Modifier and Type | Description |
---|---|---|
add(E e) | boolean | Appends an element to a list. |
add(int index, E element) | void | Inserts the element at the provided index. |
set(int index) | E | Replaces the element at the provided index with the provided one. |
remove(int index) | E | Removes and returns the element at the provided index. |
remove(Object o) | boolean | Removes the first occurrence of an object. |
get(int index) | e | Returns the element at the provided index. |
indexOf(Object o) | int | Returns the index of the first occurrence of an object. |
lastIndexOf(Object o) | int | Returns the index of the last occurrence of an object. |
contains(Object o) | boolean | Checks if the list has the given element. |
isEmpty() | boolean | Checks if the list has no elements. |
size() | int | Returns the number of elements in the list. |
clear() | void | Removes all elements from the list. The list remains allocated and can be reused. |
In the method signatures, the placeholder E
is the element type of the list. For example, for List<String>
, E
is String
.
Note: The E
is not required when calling methods. It resolves based on the type parameter of List
as shown in the examples.
Java List Classes
The JCF provides several List
interface implementations. Each class has unique behaviors that make it suitable for different use cases. Choosing between them depends on access speed, insert/remove efficiency, and thread safety.
The sections below provide a brief overview of different list classes.
ArrayList
ArrayList
is the most common implementation of the List interface. It represents a dynamic, resizable array with fast random access to elements through indices. Use the implementation when iteration and frequent access are required.
The syntax is:
List<E> name = new ArrayList<>();
Note that inserting elements in the middle of the list is slow since it requires shifting elements. It also requires external synchronization through Collections.synchronizedList()
or a similar mechanism in multi-threaded applications.
Vector
Vector
is similar to ArrayList
in structure and functionality. The main difference is that it's synchronized, making it thread-safe. All operations automatically lock, and safe access is ensured across multiple threads.
The syntax is:
List<E> name = new Vector<>();
The built-in synchronization adds overhead, making it slower than ArrayList
when working with a single thread. Vectors are considered legacy (not deprecated), and developers are encouraged to use newer concurrent collections for thread safety.
Stack
Stack
is a Vector
subclass that represents a standard LIFO stack data structure. It has specialized methods like push()
, peek()
, and pop()
to respect stack element order.
The syntax is:
Stack<E> name = new Stack<>();
It is also considered legacy, even though it's part of the JCF. Modern code uses implementations of the Deque
interface instead for better performance and predictable behavior.
Note: Read more about stack vs. heap differences.
LinkedList
LinkedList
implements the List
and Deque
interfaces and works as a list and a queue. It has a doubly linked list structure, so it's highly efficient at inserting and deleting elements from the ends.
The syntax is:
List<E> name = new LinkedList<>();
Accessing elements by index is slower because it requires traversal from either end of the list. It's suitable for cases with frequent insertions at the list ends.
Conclusion
This guide provided an in-depth look at the Java List
interface. It showed practical examples, available methods, and different class implementations.
For more Java dev topics, see how to convert a string to an integer in Java.