Predict the output · Java
Collections
Lists, sets and maps: order, duplicates, removal and missing keys.
Learn: Predicting what Java collections print7 minute read
Collections are the classes that hold groups of values: lists, sets and maps. Test code uses them constantly, for test data, expected results and API responses. Collection questions test whether you know what each type promises (order, duplicates, what happens with a missing value) and a few method traps that cause real bugs. These rules cover nearly all of them.
Lists keep order and allow duplicates
A List keeps elements in insertion order (the order in which you added them), indexed from 0, and allows duplicates. The type in angle brackets, as in List<Integer>, says what the list holds: here, Integer values. It has two remove methods: remove(int index) and remove(Object value). The compiler picks one from the argument's type. On a List<Integer>, remove(1) passes an int, so it removes by position. To remove the value 1, pass Integer.valueOf(1), which makes an Integer object (see Numbers and arithmetic for boxed numbers).
Sets drop duplicates
A Set holds each value once. add returns true when the set changed and false for a duplicate, without any error. A HashSet promises no order, so you cannot predict its printed order from the code. A LinkedHashSet keeps insertion order and a TreeSet keeps sorted order. A TreeSet also offers first(), last() and headSet(x), which holds the values strictly below x.
Maps replace values for an existing key
A map holds one value per key. put on an existing key replaces the value and returns the old one; for a new key it returns null. get on a missing key returns null; getOrDefault returns the default you give. Ordering follows the same pattern as sets: HashMap promises none, LinkedHashMap keeps insertion order (replacing a value does not move the key), and TreeMap sorts by key. A key is the name you look a value up by, and an entry is one key with its value.
import java.util.*;
public class Main {
public static void main(String[] args) {
List<Integer> nums = new ArrayList<>(List.of(5, 6, 7));
nums.remove(0);
nums.remove(Integer.valueOf(7));
System.out.println(nums);
Set<String> seen = new TreeSet<>(List.of("b", "a", "b"));
System.out.println(seen + " " + seen.add("a"));
Map<String, Integer> m = new LinkedHashMap<>();
m.put("x", 1);
System.out.println(m.put("x", 2) + " " + m + " " + m.get("y"));
}
}
[6]
[a, b] false
1 {x=2} null
Sorting and counting
Natural order for strings compares character codes, so every capital letter comes before every lower-case letter. Use String.CASE_INSENSITIVE_ORDER for alphabetical order. Java's list sort is stable: equal elements keep their order. To count things, map.merge(key, 1, Integer::sum) stores 1 for a new key and adds 1 to an existing one (Integer::sum is a short way to name the method that adds two numbers).
import java.util.*;
public class Main {
public static void main(String[] args) {
List<String> names = new ArrayList<>(List.of("bob", "Al", "Dave"));
Collections.sort(names);
System.out.println(names);
Map<String, Integer> counts = new TreeMap<>();
for (String w : List.of("b", "a", "b")) {
counts.merge(w, 1, Integer::sum);
}
System.out.println(counts);
}
}
[Al, Dave, bob]
{a=1, b=2}
Duplicates are decided by equals and hashCode
Hash-based sets and maps use hashCode (a number computed from an object, used to find it quickly) and equals (the check for "same content") to spot an existing element. A class that does not override them (write its own versions) treats every object as different, so two equal-looking objects both get added, and contains with a new equal-looking object returns false. Records, strings and wrapper types already compare by value. Sorted collections use compareTo or a Comparator instead; both are ways to say which of two values comes first.
Some lists cannot change size
List.of(...) returns a list that cannot be changed at all: add, remove and set throw UnsupportedOperationException, an error that stops the program. Arrays.asList(array) returns a fixed-size view of the array (a list that shows the array's data without holding its own copy): set works and writes into the array, but add and remove throw. Wrap either in new ArrayList<>(...) for a normal list.
Do not change a list inside its for-each loop
A for-each loop (for (String s : list)) uses an iterator behind the scenes. An iterator is an object that walks over the items one by one. Adding or removing through the list itself makes the iterator throw ConcurrentModificationException on its next step. One case confuses people: removing the second-to-last element ends the loop quietly, because the size check in hasNext() fails first, and the last element is never visited. Use removeIf or Iterator.remove().
import java.util.*;
public class Main {
public static void main(String[] args) {
List<Integer> nums = new ArrayList<>(List.of(1, 2, 3, 4));
nums.removeIf(n -> n % 2 == 0);
System.out.println(nums);
List<Integer> fixed = List.of(1, 2);
try {
fixed.add(3);
} catch (UnsupportedOperationException e) {
System.out.println("List.of is read-only");
}
}
}
[1, 3] List.of is read-only
How to answer in an interview
Name the collection's promise before you trace: "It is a TreeMap, so the keys print sorted." For a trap, say the output and the reason, then the safe alternative, for example "it throws ConcurrentModificationException; I would use removeIf". That last part shows you would write correct test code, not only predict output.
Common mistakes
- Predicting an order for a
HashSetorHashMap. - Reading
remove(1)on a list of numbers as "remove the value 1". - Expecting
geton a missing key to throw. - Putting objects without
equalsandhashCodeinto aHashSet. - Calling
addon a list fromList.oforArrays.asList.
Recap
Lists keep order and duplicates, sets drop duplicates, and maps keep one value per key. Hash collections promise no order, linked ones keep insertion order and tree ones sort. Equality comes from equals and hashCode. Some lists are read-only or fixed-size, and you should never change a list inside its own for-each loop.
11 questions0/11 solved
| Status | Question | Difficulty | Asked in |
|---|---|---|---|
| Not started | Adding a duplicate to a Set | Easy | |
| Not started | Putting the same key twice in a Map | Easy | |
| Pro+ | list.remove(1): index or value? | Easy-Medium | |
| Pro+ | A TreeSet built from a list with repeats | Easy-Medium | |
| Pro+ | TreeMap order versus LinkedHashMap order | Medium | Asked in: Capgemini, Wipro |
| Pro+ | Counting words with merge and getOrDefault | Medium | Asked in: Capgemini, ISS STOXX |
| Pro+ | Sorting strings with different cases | Medium | |
| Pro+ | Arrays.asList: write-through and fixed size | Medium | Asked in: Capgemini, Wipro |
| Pro+ | Removing from a list inside for-each | Medium-Hard | Asked in: Capgemini, Wipro |
| Pro+ | A HashSet of objects without equals and hashCode | Medium-Hard | Asked in: Cognitree, Deloitte |
| Pro+ | Removing the second-to-last element in for-each | Hard |
The first 2 questions of each topic are free. Pro+ opens every question.