Lists, sets, and maps
Exceptions, collections and modern Java12 min readLesson 4 of 6
4.1 Three shapes of collection
The collections framework groups objects. A List keeps an order and allows duplicates. A Set keeps each value at most once. A Map stores keys and values, with one value per key.
ArrayList is the usual List implementation. HashSet is the usual Set, and TreeSet keeps values sorted. HashMap is the usual Map; TreeMap keeps keys sorted.
Declare the variable as the interface type when the implementation may change: List<String> names = new ArrayList<>();. The rest of the code then depends on list operations, so the implementation can change later.
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> topics = new ArrayList<>();
topics.add("Strings");
topics.add("Collections");
topics.add("Strings");
System.out.println(topics);
System.out.println(topics.size());
System.out.println(topics.get(1));
}
}Output
[Strings, Collections, Strings] 3 Collections
4.1.1 List operations
add(value) appends, add(index, value) inserts, get(index) reads, set(index, value) replaces, and remove(index) deletes by position. size() reports the count. contains(value) uses equals.
remove has two overloads on a list of objects. remove(1) removes by index; remove(Integer.valueOf(1)) removes the value 1 from a list of integers. The argument type selects the overload.
A list prints in brackets when passed to println. The order is the insertion order for ArrayList, and an index remains valid only while the list is not changed.
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("Asha");
names.add("Ravi");
names.add(1, "Meera");
names.set(0, "Anil");
System.out.println(names);
System.out.println(names.contains("Ravi"));
}
}Output
[Anil, Meera, Ravi] true
4.1.2 Set behavior
A Set rejects a duplicate according to equals and, for hash-based sets, the hash code. Adding the same value twice leaves the size unchanged. The add method returns false when the value was already present.
HashSet does not promise an order. TreeSet sorts its elements, so printing a TreeSet gives a predictable order and iteration is sorted. A TreeSet requires elements that can be compared.
Sets are useful for tags and membership tests. They are not the right choice when the position of an element matters.
import java.util.Set;
import java.util.TreeSet;
public class Main {
public static void main(String[] args) {
Set<String> tags = new TreeSet<>();
tags.add("java");
tags.add("collections");
tags.add("java");
System.out.println(tags);
System.out.println(tags.size());
System.out.println(tags.contains("collections"));
}
}Output
[collections, java] 2 true
4.1.3 Map operations
put(key, value) adds or replaces an entry and returns the previous value, or null. get(key) returns the value or null when the key is missing. containsKey and containsValue answer presence questions. size() counts entries.
A HashMap does not promise key order. A TreeMap sorts keys. A LinkedHashMap keeps insertion order, which helps when output must follow the order in which entries were added.
Iterate with entrySet() when both key and value are needed. keySet() and values() are useful when only one side matters. Removing from a map while iterating over its views needs care, so use removeIf or an iterator.
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<String, Integer> stock = new HashMap<>();
stock.put("pen", 12);
stock.put("book", 4);
stock.put("pen", 15);
System.out.println(stock.get("pen"));
System.out.println(stock.size());
System.out.println(stock.containsKey("book"));
}
}Output
15 2 true
4.1.4 Choosing and immutable factories
Choose by the operations that dominate. A list suits ordered data with duplicates. A set suits uniqueness and membership checks. A map suits lookup by key. Sorted implementations cost more per operation than hash-based ones, so use them when order matters.
List.of(...), Set.of(...), and Map.of(...) create compact immutable collections. They are convenient for constants and test data. Adding to them throws UnsupportedOperationException.
ArrayList is a good default for a list. HashSet is a good default for a set, and HashMap for a map. Change the implementation only when a requirement, such as sorted output, calls for it.
import java.util.List;
import java.util.Map;
public class Main {
public static void main(String[] args) {
List<String> days = List.of("Mon", "Tue", "Wed");
Map<String, Integer> prices = Map.of("pen", 10, "book", 80);
System.out.println(days);
System.out.println(prices.get("book"));
System.out.println(days.contains("Tue"));
}
}Output
[Mon, Tue, Wed] 80 true
4.1.5 Iterating a map
A for-each loop over entrySet() gives a Map.Entry with getKey() and getValue(). The order depends on the map implementation. A TreeMap sorts by key, which makes the output stable and easy to check.
A lambda can shorten the loop: map.forEach((key, value) -> ...). The loop stays clearer when the body has several steps or needs a local variable.
Do not assume HashMap order in output or tests. If the order matters, choose TreeMap or LinkedHashMap, or sort the keys before printing.
import java.util.Map;
import java.util.TreeMap;
public class Main {
public static void main(String[] args) {
Map<String, Integer> totals = new TreeMap<>();
totals.put("books", 3);
totals.put("pens", 12);
totals.put("bags", 1);
for (Map.Entry<String, Integer> entry : totals.entrySet()) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
}
}Output
bags=1 books=3 pens=12
4.1.6 Practice
- Create a list of topics with a duplicate and print it.
- Create a
TreeSetfrom the same values and print the sorted result. - Build a map of item to quantity, update one entry, and print the value and size.
- Iterate a
TreeMapand print each key with its value. - Make an immutable list with
List.ofand try to add to it, reading the exception.
For step 3, print the map before and after the update. The size should stay the same while the value changes.
