List in Java
Learn about ordered collections that can contain duplicates
💡 Think of a List like a shopping list - items are kept in order, you can have duplicates (like buying 2 apples), and each item has a numbered position! You can add items at the end, insert them in the middle, or remove specific items by their position.
📝 What is a List?
A List is an ordered collection (sequence) that can contain duplicate elements. Each element has an index position starting from 0. Lists maintain insertion order and allow you to access elements by their position.
import java.util.ArrayList;import java.util.List;public class BasicArrayList { public static void main(String[] args) { // Creating an ArrayList List<String> fruits = new ArrayList<>(); // Adding elements fruits.add("Apple"); // [Apple] fruits.add("Banana"); // [Apple, Banana] fruits.add("Orange"); // [Apple, Banana, Orange] fruits.add("Apple"); // [Apple, Banana, Orange, Apple] - duplicates OK! // Getting elements by index System.out.println("First fruit: " + fruits.get(0)); // Apple System.out.println("Third fruit: " + fruits.get(2)); // Orange // Size of the list System.out.println("Total fruits: " + fruits.size()); // 4 // Checking if element exists System.out.println("Has Banana? " + fruits.contains("Banana")); // true // Removing elements fruits.remove("Banana"); // Remove by value fruits.remove(0); // Remove by index (removes "Apple") System.out.println("After removal: " + fruits); // [Orange, Apple] }}🔍 🎯 Types of Lists
Java provides different List implementations for different needs:
ArrayList
Fast random access using indexes, but slower when inserting/removing in the middle
LinkedList
Fast insertion and removal anywhere, but slower random access
Vector
Thread-safe version of ArrayList (rarely used in modern code)
Stack
Last-In-First-Out (LIFO) structure extending Vector
import java.util.LinkedList;import java.util.List;public class LinkedListExample { public static void main(String[] args) { // LinkedList is great for frequent insertions/deletions LinkedList<String> tasks = new LinkedList<>(); // Adding elements tasks.add("Task 1"); tasks.add("Task 2"); tasks.add("Task 3"); // Adding at specific positions tasks.addFirst("Urgent Task"); // Add at beginning tasks.addLast("Final Task"); // Add at end tasks.add(2, "Middle Task"); // Add at index 2 System.out.println(tasks); // [Urgent Task, Task 1, Middle Task, Task 2, Task 3, Final Task] // LinkedList can also work as a Queue tasks.removeFirst(); // Remove from beginning tasks.removeLast(); // Remove from end // Peek at elements without removing System.out.println("First: " + tasks.getFirst()); System.out.println("Last: " + tasks.getLast()); }}🛒 Real-World Example: Shopping List App
import java.util.ArrayList;import java.util.List;public class ShoppingList { private List<String> items; public ShoppingList() { this.items = new ArrayList<>(); } // Add item to the list public void addItem(String item) { items.add(item); System.out.println("Added: " + item); } // Add item at specific position public void addItemAt(int position, String item) { if (position >= 0 && position <= items.size()) { items.add(position, item); System.out.println("Inserted " + item + " at position " + position); } } // Remove item by name public void removeItem(String item) { if (items.remove(item)) { System.out.println("Removed: " + item); } else { System.out.println(item + " not found!"); } } // Check if item is on the list public boolean hasItem(String item) { return items.contains(item); } // Get total items public int getTotalItems() { return items.size(); } // Print the list public void printList() { System.out.println("\n=== Shopping List ==="); if (items.isEmpty()) { System.out.println("List is empty!"); } else { for (int i = 0; i < items.size(); i++) { System.out.println((i + 1) + ". " + items.get(i)); } } System.out.println("Total items: " + items.size()); } public static void main(String[] args) { ShoppingList myList = new ShoppingList(); // Building the shopping list myList.addItem("Milk"); myList.addItem("Bread"); myList.addItem("Eggs"); myList.addItem("Butter"); myList.printList(); // Forgot something important! myList.addItemAt(0, "Coffee"); // Add at the top myList.printList(); // Already bought milk myList.removeItem("Milk"); myList.printList(); // Check if we need eggs System.out.println("\nNeed eggs? " + myList.hasItem("Eggs")); }}📚 Real-World Example: Student Grades
import java.util.ArrayList;import java.util.Collections;import java.util.List;public class StudentGrades { public static void main(String[] args) { // Store test scores List<Integer> scores = new ArrayList<>(); // Add scores scores.add(85); scores.add(92); scores.add(78); scores.add(95); scores.add(88); System.out.println("Scores: " + scores); // Calculate average double sum = 0; for (int score : scores) { sum += score; } double average = sum / scores.size(); System.out.println("Average: " + average); // Find highest and lowest int highest = Collections.max(scores); int lowest = Collections.min(scores); System.out.println("Highest: " + highest); System.out.println("Lowest: " + lowest); // Sort scores Collections.sort(scores); System.out.println("Sorted: " + scores); // Reverse sort (highest first) Collections.sort(scores, Collections.reverseOrder()); System.out.println("Descending: " + scores); // Count scores above 90 int highScores = 0; for (int score : scores) { if (score >= 90) { highScores++; } } System.out.println("Scores >= 90: " + highScores); }}🔧 Common List Operations
import java.util.ArrayList;import java.util.Arrays;import java.util.List;public class ListOperations { public static void main(String[] args) { List<String> colors = new ArrayList<>(); // 1. Adding elements colors.add("Red"); colors.add("Blue"); colors.add("Green"); colors.addAll(Arrays.asList("Yellow", "Purple")); // 2. Accessing elements String first = colors.get(0); String last = colors.get(colors.size() - 1); // 3. Modifying elements colors.set(1, "Dark Blue"); // Replace "Blue" with "Dark Blue" // 4. Searching int index = colors.indexOf("Green"); // Returns 2 boolean hasRed = colors.contains("Red"); // Returns true // 5. Removing elements colors.remove("Yellow"); // Remove by value colors.remove(0); // Remove by index colors.removeIf(c -> c.startsWith("D")); // Remove if condition met // 6. Size and empty check int size = colors.size(); boolean isEmpty = colors.isEmpty(); // 7. Iteration System.out.println("Using for-each:"); for (String color : colors) { System.out.println(color); } System.out.println("\nUsing index:"); for (int i = 0; i < colors.size(); i++) { System.out.println(i + ": " + colors.get(i)); } // 8. Sublist List<String> subList = colors.subList(0, 2); // From index 0 to 1 // 9. Converting to array String[] colorArray = colors.toArray(new String[0]); // 10. Clearing the list colors.clear(); System.out.println("\nList cleared. Size: " + colors.size()); }}⚖️ List vs Array
import java.util.ArrayList;import java.util.Arrays;import java.util.List;public class ListVsArray { public static void main(String[] args) { // ARRAY: Fixed size, can't grow String[] arrayNames = new String[3]; arrayNames[0] = "Alice"; arrayNames[1] = "Bob"; arrayNames[2] = "Charlie"; // arrayNames[3] = "David"; // ERROR! Index out of bounds System.out.println("Array: " + Arrays.toString(arrayNames)); // LIST: Dynamic size, can grow and shrink List<String> listNames = new ArrayList<>(); listNames.add("Alice"); listNames.add("Bob"); listNames.add("Charlie"); listNames.add("David"); // Works fine! listNames.add("Eve"); // Keep adding! System.out.println("List: " + listNames); // Converting between array and list // Array to List String[] fruits = {"Apple", "Banana", "Orange"}; List<String> fruitList = new ArrayList<>(Arrays.asList(fruits)); // List to Array String[] fruitArray = fruitList.toArray(new String[0]); // Key differences: System.out.println("\n=== Key Differences ==="); System.out.println("Array size is fixed: " + arrayNames.length); System.out.println("List size is dynamic: " + listNames.size()); System.out.println("\nArray uses length property"); System.out.println("List uses size() method"); System.out.println("\nArray: faster, less memory"); System.out.println("List: flexible, more features"); }}🔑 Key Concepts
Ordered Collection
Elements maintain the order they were inserted
If you add [A, B, C], they stay in that exact order
Indexed Access
Access elements by their position number (0-based)
list.get(0) returns the first element
Duplicates Allowed
You can have the same element multiple times
[Apple, Banana, Apple] is perfectly fine
Dynamic Size
Lists grow and shrink automatically as you add/remove elements
No need to declare size upfront like arrays
✨ Best Practices
- ✓Use ArrayList by default unless you need frequent insertions/deletions
- ✓Specify initial capacity if you know the approximate size: new ArrayList<>(100)
- ✓Use enhanced for-loop or streams instead of manual indexing when possible
- ✓Prefer List<String> interface type over ArrayList<String> in declarations
- ✓Use List.of() or Arrays.asList() for creating immutable lists
- ✓Avoid removing elements during iteration without using Iterator.remove()
💼 Interview Tips
- •Know the difference between ArrayList (array-backed) and LinkedList (doubly-linked nodes)
- •ArrayList is O(1) for get/set, O(n) for add/remove in middle
- •LinkedList is O(n) for get/set, O(1) for add/remove at ends
- •Understand that ArrayList needs to resize and copy when capacity exceeded
- •Remember that List maintains insertion order unlike Set
- •Know how to convert between arrays and lists
- •Understand fail-fast behavior with ConcurrentModificationException