Lists: List, ArrayList, and Generics

First lesson of the Collections, Streams, and Exceptions course, free to read: about 15 minutes, 3 exercises and 3 quiz questions. This is the catalogue's base lesson; in the student space, it is rewritten for your profile.

Objectives

  • Create and manipulate a List<T> with ArrayList
  • Distinguish a mutable list from an immutable list (List.of)
  • Iterate over and filter a list without triggering a ConcurrentModificationException

Collections frameworkList and ArrayListGeneric types

A Java array (int[]) has a fixed size: you cannot add an element once it is created. In a real program (a shopping cart, a list of students, the lines of a file), you do not know the size in advance. The Collections framework (java.util) addresses this need, and the most widely used collection is the list.

Declaring a list

import java.util.ArrayList;
import java.util.List;

List<String> courses = new ArrayList<>(); // interface on the left, implementation on the right
courses.add("bread");          // adds at the end
courses.add("milk");
courses.add(0, "coffee");       // inserts at index 0
System.out.println(courses);  // [coffee, bread, milk]
System.out.println(courses.get(1));   // bread
courses.set(1, "baguette");   // replaces the element at index 1
System.out.println(courses.size());   // 3
System.out.println(courses.contains("milk")); // true

Since Java 21, lists are sequenced collections: they offer shortcuts for the ends, more readable than get(0) or get(list.size() - 1):

courses.getFirst();           // "coffee"  (NoSuchElementException if the list is empty)
courses.getLast();            // "milk"
courses.addFirst("tea");      // equivalent to add(0, "tea")
courses.reversed();           // view in reverse order: [milk, baguette, coffee, tea]

The <String> is a generic type: the compiler refuses to add anything other than a String, and get returns a String directly, without casting. The diamond operator <> avoids repeating the type.

Generics accept only objects: you write List<Integer>, not List<int>. Java automatically converts int to Integer (autoboxing).

Why declare with List rather than ArrayList? So you can switch implementations (for example to LinkedList) without touching the rest of the code. This is the principle of “programming to an interface”.

The remove trap

List<Integer> notes = new ArrayList<>(List.of(10, 20, 30));
notes.remove(1);                    // removes the element at INDEX 1 -> [10, 30]
notes.remove(Integer.valueOf(30));  // removes the VALUE 30 -> [10]

Immutable lists

List.of("a", "b") creates an unmodifiable list: add or remove throws an UnsupportedOperationException. This is ideal for constants or for returning data you do not want modified. To get a modifiable copy: new ArrayList<>(List.of(...)). For an immutable copy of an existing list: List.copyOf(list).

Iterating and removing safely

for (String article : courses) {
    System.out.println("- " + article);
}

// Classic ERROR: removing during a for-each
// for (String a : courses) { if (a.startsWith("b")) courses.remove(a); }
// -> ConcurrentModificationException

courses.removeIf(a -> a.startsWith("b")); // the right way

removeIf takes a condition (a lambda, which we will cover in depth in lesson 3) and removes all the elements that satisfy it.

Key takeaways

  • ArrayList is the default list: fast index access, fast append.
  • Declare with the List<T> interface.
  • List.of = immutable; new ArrayList<>(...) = modifiable.
  • No removal inside a for-each: use removeIf.

Exercises

Solutions and tests stay on the server. In the student space, your code is run and checked, and the tutor gives hints before the solution.

  1. CodeDifficulty 1Server sandbox2 hints

    Clean a list of measurements

    Read a line of integers separated by spaces. Store them in a List<Integer>, remove the negative values with removeIf, then print:

    [3, 4, 9]
    taille=3
    somme=16

    (the list with System.out.println(list), then its size, then the sum). An empty line gives an empty list.

    import java.util.*;
    
    public class Main {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            String ligne = sc.hasNextLine() ? sc.nextLine().trim() : "";
            List<Integer> mesures = new ArrayList<>();
            // TODO : remplir la liste, supprimer les négatifs, afficher
        }
    }
  2. CodeDifficulty 2Server sandbox2 hints

    Shopping list driven by commands

    Each input line is a command:

    • ADD x: appends x at the end;
    • INSERT i x: inserts x at index i;
    • REMOVE x: removes the first occurrence of x, or prints absent: x if it does not exist.

    At the end, print the list numbered from 1 (1. pain). If the list is empty, print liste vide.

    import java.util.*;
    
    public class Main {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            List<String> courses = new ArrayList<>();
            while (sc.hasNextLine()) {
                String[] p = sc.nextLine().trim().split(" ");
                // TODO : traiter ADD, INSERT et REMOVE
            }
            // TODO : afficher la liste numérotée
        }
    }
  3. Multiple choiceDifficulty 11 hint

    Immutable list

    What happens when List<String> l = List.of("a"); l.add("b"); runs?

    • The list contains [a, b]
    • An UnsupportedOperationException is thrown
    • The code does not compile
    • add returns false without changing anything

End-of-lesson quiz

  1. Which declaration is recommended?

    • ArrayList<String> l = new ArrayList<String>();
    • List<String> l = new ArrayList<>();
    • List l = new ArrayList();
  2. On a List equal to [5, 6, 7], what does remove(1) give?

    • [6, 7]
    • [5, 7]
    • [5, 6, 7]
  3. How do you remove all empty elements from a modifiable List?

    • In a for-each with list.remove(s)
    • liste.removeIf(String::isEmpty)
    • liste.delete("")

The rest of the course

  1. Sets and Dictionaries: Set and Map18 min
  2. Lambdas, Comparator, and Your First Streams18 min
  3. Collectors, Grouping, and Optional18 min
  4. Handling Errors with Exceptions20 min

Collections, Streams, and Exceptions · Intermediate · 2 h 29 min