Java · Collections · Topic 2
List Interface
Learn how Java lists preserve sequence, permit duplicates, support indexes, and differ through ArrayList, LinkedList, Vector, and Stack.
Step 1 of 9
2.1 Introduction to List
Explain the defining behavior of a List and read element positions using zero-based indexes.
List is a child interface of Collection. It stores elements in a sequence, maintains their order, and assigns every element a zero-based index.
Important List properties
- Maintains element order
- Allows duplicate elements
- Normally allows null values
- Supports insertion, access, update, and removal by index
List<String> names = new ArrayList<>();
names.add("Amit");
names.add("Neha");
names.add("Amit");| Index | Value |
|---|---|
| 0 | Amit |
| 1 | Neha |
| 2 | Amit |
Check your understanding: Why can the same student name appear more than once in a List?
Because List permits duplicate elements and treats each position as a separate entry.
Step 2 of 9
2.2 Creating a List
Declare a List using an interface reference and explain each part of the generic declaration.
The recommended declaration uses List as the reference type and an implementation such as ArrayList as the object. This keeps the program flexible.
List<String> names = new ArrayList<>();
// The implementation can be changed later:
List<String> otherNames = new LinkedList<>();Reading the declaration
- List is the interface
- ArrayList is the implementation class
- String is the element type
- The diamond operator <> lets Java infer the type
Check your understanding: In List<String> names = new ArrayList<>(), what does String specify?
It specifies the type of element the list may store.
Step 3 of 9
2.3 Important methods of the List interface
Use the core List methods for inserting, reading, updating, removing, searching, sizing, and clearing elements.
| Operation | Example | Purpose |
|---|---|---|
| Add | list.add("Java") | Appends an element |
| Insert | list.add(1, "C++") | Inserts at an index |
| Access | list.get(0) | Returns the indexed element |
| Update | list.set(0, "Advanced Java") | Replaces an indexed element |
| Remove by index | list.remove(1) | Removes the indexed element |
| Remove by value | list.remove("Python") | Removes a matching object |
| Search | list.contains("Java") | Checks membership |
| Locate | list.indexOf("Java") | Returns the first matching index |
| Size | list.size() | Returns the element count |
| Clear | list.clear() | Removes every element |
list.add("Java");
list.add("Python");
list.add(1, "C++");
String subject = list.get(0);
list.set(0, "Advanced Java");
list.remove("Python");
int total = list.size();Check your understanding: Which method replaces the value stored at index 0?
list.set(0, newValue).
Step 4 of 9
2.4 ArrayList
Describe ArrayList storage, performance, and suitable use cases, then trace a complete program.
ArrayList is a resizable-array implementation of List. When capacity is insufficient, it creates a larger internal array and transfers the elements.
ArrayList characteristics
- Maintains insertion order
- Allows duplicates and null
- Grows automatically
- Provides fast index-based access
- Middle insertions and removals may shift elements
- Is not synchronized by default
import java.util.ArrayList;
import java.util.List;
public class ArrayListDemo {
public static void main(String[] args) {
List<String> subjects = new ArrayList<>();
subjects.add("Java");
subjects.add("Python");
subjects.add("Database");
subjects.add("Java");
System.out.println(subjects);
System.out.println("First subject: " + subjects.get(0));
subjects.set(1, "C++");
subjects.remove("Database");
System.out.println("Updated list: " + subjects);
}
}[Java, Python, Database, Java]
First subject: Java
Updated list: [Java, C++, Java]| Operation | Complexity |
|---|---|
| get(index) | O(1) |
| set(index) | O(1) |
| Add at end | Usually O(1) |
| Insert in middle | O(n) |
| Remove from middle | O(n) |
| Search by value | O(n) |
Check your understanding: Why is middle insertion slower in an ArrayList?
Existing elements may need to be shifted to make room.
Step 5 of 9
2.5 LinkedList
Explain the doubly linked structure, use both-end methods, and compare its access costs with ArrayList.
LinkedList implements List and Deque. Each node stores data plus references to the previous and next nodes. Conceptually: null <- [A] <-> [B] <-> [C] -> null.
LinkedList characteristics
- Maintains insertion order
- Allows duplicates and null
- Supports both-end insertion and removal
- Does not provide fast random access
- Can act as a list, queue, or deque
- Is not synchronized by default
import java.util.LinkedList;
public class LinkedListDemo {
public static void main(String[] args) {
LinkedList<String> cities = new LinkedList<>();
cities.add("Anand");
cities.add("Vadodara");
cities.add("Ahmedabad");
cities.addFirst("Nadiad");
cities.addLast("Surat");
System.out.println(cities);
cities.removeFirst();
cities.removeLast();
System.out.println("After removal: " + cities);
}
}[Nadiad, Anand, Vadodara, Ahmedabad, Surat]
After removal: [Anand, Vadodara, Ahmedabad]| Method | Purpose |
|---|---|
| addFirst(element) | Adds at the beginning |
| addLast(element) | Adds at the end |
| getFirst() | Gets the first element |
| getLast() | Gets the last element |
| removeFirst() | Removes the first element |
| removeLast() | Removes the last element |
| offer(element) | Adds using queue behavior |
| poll() | Retrieves and removes the first element |
| peek() | Reads the first element without removal |
| Operation | Complexity |
|---|---|
| get(index) | O(n) |
| Add or remove at beginning | O(1) |
| Add or remove at end | O(1) |
| Search by value | O(n) |
| Locate a middle position | O(n) |
Check your understanding: Why is get(index) normally O(n) for LinkedList?
The list must follow node links until it reaches the requested position.
Step 6 of 9
2.6 Vector
Recognize Vector as a legacy synchronized resizable array and distinguish size from capacity.
Vector characteristics
- Resizable array that maintains order
- Allows duplicates and null
- Supports index access
- Synchronizes its main methods
- Legacy class with synchronization overhead
import java.util.Vector;
public class VectorDemo {
public static void main(String[] args) {
Vector<String> subjects = new Vector<>();
subjects.add("Java");
subjects.add("Python");
subjects.add("Database");
System.out.println(subjects);
System.out.println("Element at index 1: " + subjects.get(1));
subjects.remove("Python");
System.out.println("After removal: " + subjects);
}
}[Java, Python, Database]
Element at index 1: Python
After removal: [Java, Database]| Legacy method | Modern equivalent |
|---|---|
| addElement(element) | add(element) |
| elementAt(index) | get(index) |
| removeElement(element) | remove(element) |
| firstElement() | get(0) |
| lastElement() | get(size() - 1) |
Vector<Integer> numbers = new Vector<>(5);
System.out.println(numbers.size()); // 0
System.out.println(numbers.capacity()); // 5Check your understanding: What is the difference between Vector size and capacity?
Size is the number of stored elements; capacity is the number that fit before resizing.
Step 7 of 9
2.7 Stack
Apply LIFO operations, interpret search positions, prevent underflow, and recognize the modern ArrayDeque alternative.
Stack extends Vector and follows Last In, First Out. The last element pushed is the first element popped.
| Method | Purpose |
|---|---|
| push(element) | Adds to the top |
| pop() | Removes and returns the top |
| peek() | Reads the top without removal |
| empty() | Checks whether the stack is empty |
| search(element) | Returns a one-based position from the top |
import java.util.Stack;
public class StackDemo {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(10);
stack.push(20);
stack.push(30);
System.out.println("Stack: " + stack);
System.out.println("Top element: " + stack.peek());
System.out.println("Removed: " + stack.pop());
System.out.println("After pop: " + stack);
System.out.println("Position of 10: " + stack.search(10));
}
}Stack: [10, 20, 30]
Top element: 30
Removed: 30
After pop: [10, 20]
Position of 10: 2| Element | Position from top |
|---|---|
| 30 | 1 |
| 20 | 2 |
| 10 | 3 |
if (!stack.empty()) {
System.out.println(stack.pop());
}Common stack applications
- Undo operations
- Browser history
- Function calls
- Expression evaluation
- Parenthesis matching
- Backtracking
- Depth-first search
Check your understanding: What happens when pop() is called on an empty Stack?
It throws EmptyStackException, so the program should check empty() first.
Step 8 of 9
2.8 Common List Operations
Trace a complete list workflow and distinguish remove(index) from remove(object) for integer lists.
import java.util.ArrayList;
import java.util.List;
public class ListOperationsDemo {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("Amit");
names.add("Neha");
names.add("Raj");
names.add(1, "Priya");
System.out.println("List: " + names);
System.out.println("Element at index 2: " + names.get(2));
names.set(2, "Riya");
System.out.println("Contains Raj: " + names.contains("Raj"));
names.remove("Amit");
names.remove(0);
System.out.println("Size: " + names.size());
for (String name : names) System.out.println(name);
System.out.println("Empty: " + names.isEmpty());
names.clear();
System.out.println("Final list: " + names);
}
}List: [Amit, Priya, Neha, Raj]
Element at index 2: Neha
Contains Raj: true
Size: 2
Riya
Raj
Empty: false
Final list: []List<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);
numbers.add(30);
List<Integer> byIndex = new ArrayList<>();
byIndex.add(10); byIndex.add(20); byIndex.add(30);
byIndex.remove(1); // Removes index 1 -> [10, 30]
List<Integer> byValue = new ArrayList<>();
byValue.add(10); byValue.add(20); byValue.add(30);
byValue.remove(Integer.valueOf(20)); // Removes value 20 -> [10, 30]Check your understanding: How do you remove the Integer value 20 rather than the element at index 20?
Use numbers.remove(Integer.valueOf(20)).
Step 9 of 9
2.9 Comparison of List Implementations
Compare List implementations and choose one from the application’s dominant operations.
| Feature | ArrayList | LinkedList | Vector | Stack |
|---|---|---|---|---|
| Data structure | Resizable array | Doubly linked list | Resizable array | LIFO stack based on Vector |
| Maintains order | Yes | Yes | Yes | Yes |
| Allows duplicates | Yes | Yes | Yes | Yes |
| Index access | Fast | Slow | Fast | Available |
| Beginning insertion | Slow | Fast | Slow | Not its main purpose |
| End insertion | Usually fast | Fast | Usually fast | push() |
| Synchronized | No | No | Yes | Yes |
| Legacy class | No | No | Yes | Yes |
| Main purpose | General-purpose list | List, queue, or deque | Legacy synchronized list | LIFO operations |
Simple selection rule
- Use ArrayList for most general list requirements
- Use LinkedList when frequent operations at both ends are required
- Understand Vector for legacy synchronized lists
- Understand Stack for LIFO, but prefer ArrayDeque in modern Java
Check your understanding: Which implementation is the normal first choice for a general-purpose List?
ArrayList.