Java List


In Java, a List is an ordered collection that allows duplicate elements. Unlike other collections like Set, a List preserves the order in which elements are inserted. It also provides the ability to access elements by their index, making it a highly versatile and frequently used collection type.

The List interface is part of the java.util package and is a core component of the Java Collections Framework. It extends the Collection interface and adds more specific methods for working with ordered collections, such as retrieving elements by index and inserting elements at specific positions.

What is a Java List?

A List is a collection that maintains the order of its elements. This means that the elements in a list are stored in the order they are inserted. You can access, insert, or remove elements based on their index position, making List particularly useful for handling ordered data.

Key characteristics of a List:

  • Ordered: Elements are stored in the order they were added.
  • Allows Duplicates: Lists allow duplicate elements, so the same element can appear multiple times in a list.
  • Indexed: Elements in a list can be accessed directly using their index (position).

Core Methods of the List Interface

The List interface in Java extends the Collection interface and provides several additional methods specific to lists. Here are some of the key methods you should be familiar with:

1. add(E e)

Adds the specified element to the list. It appends the element to the end of the list.

List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
System.out.println(list);  // Output: [Java, Python]

2. add(int index, E element)

Inserts the specified element at the specified position in the list. Shifts the element currently at that position (if any) and any subsequent elements to the right.

List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add(1, "C++");
System.out.println(list);  // Output: [Java, C++, Python]

3. get(int index)

Returns the element at the specified position in the list.

List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
System.out.println(list.get(1));  // Output: Python

4. remove(int index)

Removes the element at the specified position in the list. Shifts any subsequent elements to the left.

List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.remove(1);  // Removes "Python"
System.out.println(list);  // Output: [Java]

5. set(int index, E element)

Replaces the element at the specified position in the list with the specified element.

List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.set(1, "C++");
System.out.println(list);  // Output: [Java, C++]

6. size()

Returns the number of elements in the list.

List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
System.out.println(list.size());  // Output: 2

7. contains(Object o)

Returns true if the list contains the specified element.

List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
System.out.println(list.contains("Java"));  // Output: true

8. indexOf(Object o)

Returns the index of the first occurrence of the specified element, or -1 if the element is not found.

List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");
System.out.println(list.indexOf("Python"));  // Output: 1

9. clear()

Removes all the elements from the list, making it empty.

List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.clear();
System.out.println(list.isEmpty());  // Output: true

Common Implementations of the List Interface

There are several concrete classes that implement the List interface, each with unique features. The most commonly used implementations include:

1. ArrayList

ArrayList is the most commonly used implementation of the List interface. It uses a dynamic array to store elements. It offers fast random access to elements and is efficient for read operations.

  • Pros: Fast random access, dynamic resizing.
  • Cons: Slower for insertions and deletions in the middle of the list due to the need for shifting elements.
List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");

2. LinkedList

LinkedList is another popular implementation of the List interface. It uses a doubly-linked list to store elements. LinkedList is better for operations that involve frequent insertions or deletions, especially at the beginning or middle of the list.

  • Pros: Fast insertions and deletions at the beginning or middle of the list.
  • Cons: Slower random access to elements compared to ArrayList.
List<String> list = new LinkedList<>();
list.add("Java");
list.add("Python");
list.add("C++");

3. Vector

Vector is an older implementation of the List interface, similar to ArrayList, but it is synchronized. This makes it thread-safe but also less performant in single-threaded scenarios.

  • Pros: Thread-safe.
  • Cons: Slower than ArrayList due to synchronization.
List<String> list = new Vector<>();
list.add("Java");
list.add("Python");

4. Stack

Stack is a subclass of Vector that represents a last-in-first-out (LIFO) stack of objects. It’s rarely used nowadays, as Deque provides more modern alternatives for stack operations.

Stack<String> stack = new Stack<>();
stack.push("Java");
stack.push("Python");
stack.pop();  // Removes "Python"

Advanced Topics in Java List

1. Iterating Through a List

You can use various methods to iterate over a list, including the enhanced for loop, Iterator, and Java 8 streams.

Using the Enhanced For Loop

List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");

for (String language : list) {
    System.out.println(language);
}

Using an Iterator

Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

Using Java 8 Streams

list.stream().forEach(System.out::println);

2. Sublist Method

The subList(int fromIndex, int toIndex) method returns a view of the portion of the list between the specified indices. It doesn’t create a new list but provides a view, meaning changes to the sublist are reflected in the original list.

List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");
List<String> subList = list.subList(0, 2);
System.out.println(subList);  // Output: [Java, Python]

3. Sorting a List

You can sort a list using Collections.sort() or List.sort(). Both methods allow you to sort the list in natural order or by providing a custom comparator.

List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");

Collections.sort(list);
System.out.println(list);  // Output: [C++, Java, Python]

Best Practices for Using Java List

  1. Choose the Right Implementation: Choose between ArrayList and LinkedList based on your needs. Use ArrayList for fast random access, and LinkedList for frequent insertions and deletions.
  2. Use Generics: Always specify the type of elements stored in the list to ensure type safety.
  3. Avoid Unnecessary Duplicates: While lists allow duplicates, ensure that the presence of duplicate elements is required for your use case.
  4. Use Enhanced For Loop or Streams for Iteration: Avoid using traditional for loops unless necessary. Use the enhanced for loop or Java Streams to make your code cleaner and more readable.