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.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
How to Use Java Stream toMap with Duplicate Keys and Null Values

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<User> userList = new ArrayList<>();
        // 模拟数据
        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);
    }
}

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<User> userList = new ArrayList<>();
        // 模拟数据
        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 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<User> userList = new ArrayList<>();
        // 模拟数据
        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);
    }
}

For comparison, the same result can be achieved with a classic for loop:

public class UserTest {
    @Test
    public void demo() {
        List<User> userList = new ArrayList<>();
        // 模拟数据
        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);
    }
}

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javaStreamoptionalnullpointerexceptionDuplicateKeytoMap
Code Ape Tech Column
Written by

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

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.