Handling Duplicate Keys and Null Values with Java Stream toMap: A Practical Guide
This article explains how to convert a list of Java User objects into a Map using Stream's toMap collector, handling duplicate keys and null values with merge functions and Optional, and compares alternative approaches including manual HashMap population.
In JDK 8, Java introduced the powerful Stream API, which has become indispensable for everyday development.
After processing a stream, developers often collect results into a List or Set using collect(Collectors.toList()) or collect(Collectors.toSet()), and may assume that collect(Collectors.toMap(...)) is equally straightforward.
However, overlooking duplicate keys can turn this assumption into a nightmare.
First, define a simple User entity class:
@Data
@AllArgsConstructor
public class User {
private int id;
private String name;
}Suppose we read a List<User> from a database and want to transform it into a Map where the key is the user's id and the value is the user's name.
A naïve implementation using Collectors.toMap(User::getId, User::getName) compiles but throws IllegalStateException at runtime because the list contains duplicate ids:
public class UserTest {
@Test
public void demo() {
List<User> userList = new ArrayList<>();
// mock data
userList.add(new User(1, "Alex"));
userList.add(new User(1, "Beth"));
Map<Integer, String> map = userList.stream()
.collect(Collectors.toMap(User::getId, User::getName));
System.out.println(map);
}
}The exception occurs because the default toMap collector does not know how to merge values for duplicate keys; we must supply a merge function.
Adding a merge function resolves the duplicate‑key issue, but if any name is null the collector throws a NullPointerException:
public class UserTest {
@Test
public void demo() {
List<User> userList = new ArrayList<>();
// mock data
userList.add(new User(1, "Alex"));
userList.add(new User(2, null));
Map<Integer, String> map = userList.stream()
.collect(Collectors.toMap(User::getId, User::getName, (oldData, newData) -> newData));
System.out.println(map);
}
}To guard against null names, we can wrap the value extraction with Optional.ofNullable(...).orElse("") while still providing a merge function, resulting in a concise and robust solution:
public class UserTest {
@Test
public void demo() {
List<User> userList = new ArrayList<>();
// mock data
userList.add(new User(1, "Alex"));
userList.add(new User(1, "Beth"));
userList.add(new User(2, null));
Map<Integer, String> map = userList.stream()
.collect(Collectors.toMap(
User::getId,
it -> Optional.ofNullable(it.getName()).orElse(""),
(oldData, newData) -> newData
));
System.out.println(map);
}
}If you prefer an explicit approach, you can iterate over the list with forEach and put entries into a HashMap manually:
public class UserTest {
@Test
public void demo() {
List<User> userList = new ArrayList<>();
// mock data
userList.add(new User(1, "Alex"));
userList.add(new User(1, "Beth"));
userList.add(new User(2, null));
Map<Integer, String> map = new HashMap<>();
userList.forEach(it -> {
map.put(it.getId(), it.getName());
});
System.out.println(map);
}
}The final version demonstrates a clean combination of Stream, Optional, and a merge function to produce a map without duplicate‑key errors or NPEs.
Join the backend‑focused technical community to share knowledge, job referrals, and industry discussions, while keeping the conversation civil and free of advertisements.
Civilized communication should focus on technical exchange, job referrals, and industry discussion.
Advertisements and private solicitations are prohibited.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
