How to Use Java Stream toMap with Duplicate Keys and Null Values
This article demonstrates how to convert a list of Java objects into a Map using Stream's toMap collector, addresses duplicate key exceptions by providing a merge function, handles null values with Optional, and compares stream-based solutions with traditional for-loop approaches.
Java 8 introduced the Stream API, which has become essential for modern Java development. One common task is converting a collection of objects into a Map using Collectors.toMap .
First, define a simple user entity:
@Data
@AllArgsConstructor
public class User {
private int id;
private String name;
}Attempting to collect a list of User objects into a map with the default collector can raise an IllegalStateException when duplicate keys are present:
public class UserTest {
@Test
public void demo() {
List
userList = new ArrayList<>();
// 模拟数据
userList.add(new User(1, "Alex"));
userList.add(new User(1, "Beth"));
Map
map = userList.stream()
.collect(Collectors.toMap(User::getId, User::getName));
System.out.println(map);
}
}Because two users share the same id , the collector throws an exception. Providing a merge function resolves the duplicate‑key problem, but a NullPointerException can still occur if a name is null :
public class UserTest {
@Test
public void demo() {
List
userList = new ArrayList<>();
// 模拟数据
userList.add(new User(1, "Alex"));
userList.add(new User(2, null));
Map
map = userList.stream()
.collect(Collectors.toMap(User::getId, User::getName, (oldData, newData) -> newData));
System.out.println(map);
}
}To safely handle null values, wrap the value extraction with Optional and provide a default, while still merging duplicates:
public class UserTest {
@Test
public void demo() {
List
userList = new ArrayList<>();
// 模拟数据
userList.add(new User(1, "Alex"));
userList.add(new User(1, "Beth"));
userList.add(new User(2, null));
Map
map = userList.stream()
.collect(Collectors.toMap(
User::getId,
it -> Optional.ofNullable(it.getName()).orElse(""),
(oldData, newData) -> newData
));
System.out.println(map);
}
}For comparison, the same result can be achieved with a classic for loop:
public class UserTest {
@Test
public void demo() {
List
userList = new ArrayList<>();
// 模拟数据
userList.add(new User(1, "Alex"));
userList.add(new User(1, "Beth"));
userList.add(new User(2, null));
Map
map = new HashMap<>();
userList.forEach(it -> {
map.put(it.getId(), it.getName());
});
System.out.println(map);
}
}These examples illustrate how to handle duplicate keys and null values when using Collectors.toMap , and show that Stream‑based solutions combined with Optional provide concise, expressive alternatives to manual loops.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
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.