Views: keySet, values and subList

Collections · lesson 32 of 42 · 4 min read

Tell a live view apart from a copy, and stop a subList blowing up underneath you.

Open this lesson in the learning hub

Key points

  • keySet(), values() and entrySet() are views: remove from one and the entry leaves the map.
  • They cannot add, because a key with no value is meaningless — add throws UnsupportedOperationException.
  • list.subList(1, 3) is a view of a range, so sorting or clearing it changes the backing list.
  • Structurally change the backing list and the subList is dead: its next call throws ConcurrentModificationException.
  • Want a copy? Wrap it: new ArrayList<>(list.subList(1, 3)) or Set.copyOf(map.keySet()).
  • A view returned from a getter leaks your internals — hand back a copy or an unmodifiable wrapper.

Example

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Map<String, Integer> stock = new LinkedHashMap<>();
        stock.put("nuts", 0);
        stock.put("bolts", 7);
        stock.put("nails", 0);

        stock.values().removeIf(v -> v == 0);
        System.out.println("values().removeIf : " + stock + "   (the map itself changed)");

        stock.keySet().remove("bolts");
        System.out.println("keySet().remove   : " + stock + "   (the view writes through)");
        try {
            stock.keySet().add("screws");
        } catch (UnsupportedOperationException e) {
            System.out.println("keySet().add      : UnsupportedOperationException");
        }

        List<Integer> nums = new ArrayList<>(List.of(9, 5, 7, 1, 3));
        List<Integer> middle = nums.subList(1, 4);
        Collections.sort(middle);
        System.out.println("sorted a subList  : " + nums + "   (the backing list re-ordered)");

        List<Integer> copy = new ArrayList<>(nums.subList(0, 2));
        copy.set(0, 99);
        System.out.println("copy of a subList : " + copy + "  backing " + nums);

        List<Integer> stale = nums.subList(0, 2);
        nums.add(42);
        try {
            stale.get(0);
        } catch (ConcurrentModificationException e) {
            System.out.println("subList after add : ConcurrentModificationException");
        }
    }
}

A view is the collection wearing a different shape. Copy it the moment you hand it away.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Collections course, and every lesson in it is listed on the Collections contents page.