This is possible using the mergeFunction parameter of Collectors.toMap(keyMapper, valueMapper, mergeFunction):

Map<String, String> phoneBook = 
    people.stream()
          .collect(Collectors.toMap(
             Person::getName,
             Person::getAddress,
             (address1, address2) -> {
                 System.out.println("duplicate key found!");
                 return address1;
             }
          ));

mergeFunction is a function that operates on two values associated with the same key. adress1 corresponds to the first address that was encountered when collecting elements and adress2 corresponds to the second address encountered: this lambda just tells to keep the first address and ignores the second.

Answer from Tunaki on Stack Overflow
🌐
Baeldung
baeldung.com › home › java › java collections › java map › handle duplicate keys when producing map using java stream
Handle Duplicate Keys When Producing Map Using Java Stream | Baeldung
January 8, 2024 - However, this approach returns Map<String, List<City>>. If we require Map<String, City> as the return type, we can no longer group the objects with the duplicated key together in a collection. So next, let’s see how to deal with the duplicated keys in this situation. Stream API has provided the toMap() collector method to collect a stream into a Map.
🌐
Javaprogramto
javaprogramto.com › 2020 › 07 › java-8-convert-list-to-map-handling-duplicate-keys.html
Java 8 - Convert List to Map (Handling Duplicate Keys) JavaProgramTo.com
Next, Run the full code as below. toMap() method, we are passing getId() as the key that means id should be unique in the list but it has duplicates for id 102. We should see the runtime exception now. package Collectors; import java.util.ArrayList; ...
Discussions

java - Ignore duplicates when producing map using streams - Stack Overflow
The other way is to "start" with ... output stream. Ugh. Here's an example that happens to survive this...sometimes... ... I got the same issue. A map stores key, value pairs and does not allow duplicate keys. If individual objects have duplicate names, you will get the error ... Map stringMap; List personList ... More on stackoverflow.com
🌐 stackoverflow.com
Java-Stream, toMap with duplicate keys - Stack Overflow
Problem statement: Converting ... List>. For Instance you have a SimpleImmutableEntry of this form [A,[1]], [B,[2]], [A, [3]] and you want your map to looks like this: A -> [1,3] , B -> [2]. This can be done with Collectors.toMap but Collectors.toMap works only with unique keys unless you provide a merge function to resolve the collision as said in java docs. https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collector... More on stackoverflow.com
🌐 stackoverflow.com
Hot Linked Questions - Stack Overflow
Is there a way to create Map directly from a groupingBy function in Java 8, instead of creating Map>? I have the following code: List... ... I have a stream of objects similar to this previous question, however, instead of ignoring duplicate values, ... More on stackoverflow.com
🌐 stackoverflow.com
How to collect into a Map forming a List in value when duplicate keys in streams, in Java 8 - Stack Overflow
I have a stream of elements in the form of either 2-D array or EntrySet. I need these to be collected in a Map. Now the issue is the stream of elements can have duplicate elements. Let's say I want... More on stackoverflow.com
🌐 stackoverflow.com
🌐
Medium
medium.com › @AlexanderObregon › javas-collectors-tomap-method-explained-f95999d4ebe6
Java's Collectors.toMap() Method Explained
October 20, 2024 - In some cases, instead of resolving collisions, you might want to avoid them altogether by making sure that your data is pre-processed or checked before passing it into the stream. For example, you can filter out duplicates before mapping or use a strategy that generates unique keys dynamically (e.g., by appending a suffix or using a composite key). Here’s an example where we generate unique keys by appending a unique suffix for each employee with a duplicate ID: List<Employee> employees = List.of( new Employee(1, "Kaitlyn"), new Employee(1, "David"), // Duplicate ID new Employee(2, "Alex"), new Employee(3, "Chuck") ); AtomicInteger counter = new AtomicInteger(1); Map<String, String> employeeMap = employees.stream() .collect(Collectors.toMap( e -> e.getId() + "-" + counter.getAndIncrement(), // Unique key with suffix Employee::getName ));
🌐
Marc Nuri
blog.marcnuri.com › home › java streams: convert list into map
Java Streams: Convert List into Map - Marc Nuri
January 27, 2026 - When you're certain that the List ... is to convert the list into a Stream and then collect the results using Collectors.toMap(). For the Map key, we use Repository::name (a method reference equivalent to r -> r.name())...
🌐
How to do in Java
howtodoinjava.com › home › java streams › java stream to map with collectors.tomap() examples
Java Stream to Map With Collectors.toMap() Examples
March 18, 2019 - List<Item> itemsWithDuplicates = List.of(new Item(1, "Item1"), new Item(2, "Item2"), new Item(3, "Item3-1"), new Item(3, "Item3-2"), new Item(3, "Item3-3")); Map<Long, String> fails = itemsWithDuplicates.stream().collect(Collectors.toMap(Item::id, Item::name)); // IllegalStateException: Duplicate key 3 (attempted merging values Item3-1 and Item3-2) Exception in thread "main" java.lang.IllegalStateException: Duplicate key 3 (attempted merging values Item3-1 and Item3-2) at java.base/java.util.stream.Collectors.duplicateKeyException(Collectors.java:135) at java.base/java.util.stream.Collectors.lambda$uniqKeysMapAccumulator$0(Collectors.java:182)
🌐
Cscode
cscode.io › java › collections › convert list to map
Convert a List to Map using Java Stream API | CsCode.io
Map<String, List<Person>> nameToPersonMap= persons.stream().collect (Collectors.toMap(Person::getGender, person-> { List<Person> personList = new ArrayList<>(); personList.add(person); return personList; } )); When you run the above code, then it will throw below exception, because Person A and Person C have same keys. Exception in thread "main" java.lang.IllegalStateException: Duplicate key Male (attempted merging values [[name : Person A , age : 29, gender : Male]] and [[name : Person C , age : 45, gender : Male]]) at java.base/java.util.stream.Collectors.duplicateKeyException(Collectors.jav
🌐
Javadevcentral
javadevcentral.com › collectors tomap duplicate key
Collectors toMap Duplicate Key | Java Developer Central
December 2, 2019 - Basically, a merge function is a BinaryOperator<T> i.e., a BiFunction<T,T,T> and we can use it to resolve collisions between values associated with the same key. In this case, when the stream pipeline encounters a duplicate key, it will call the merge function with both the values i.e., the value already mapped to the current (duplicate) key and the new value (result of the value mapper function for the current stream element).
Find elsewhere
🌐
JDriven
jdriven.com › blog › 2021 › 02 › Java-Joy-Merge-Maps-Using-Stream-API
Java Joy: Merge Maps Using Stream API - JDriven Blog
February 26, 2021 - In the following example we use the Stream API to merge multiple Map instances into a new Map using a remapping function for duplicate keys: package com.mrhaki.sample; import java.util.Arrays; import java.util.HashSet; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; public class MapMerge { public static void main(String[] args) { Map<Character, Integer> first = Map.of('a', 2, 'b', 3, 'c', 4); Map<Character, Integer> second = Map.of('a', 10, 'c', 11); Map<Character, Integer> third = Map.of('a', 3, 'd', 100); // First we turn multiple maps into a stream of entries and // in the collect method we create a new map and define // a function to multiply the entry value when there is a // duplicate entry key.
🌐
Stack Overflow
stackoverflow.com › questions › linked › 32312876
Hot Linked Questions - Stack Overflow
I am seeing Duplicate key , illegal state Exception. List<User> allusers = Helper.getAllUsers(someKey); Map<String, User> allusersMap = allusers.stream() .collect(... ... my problem is that I get java.lang.IllegalStateException: Duplicate key every time I try to map a String with List.
🌐
Signavio
tech.signavio.com › 2018 › java-stream-collect-pitfalls
Trouble building maps with the Java Stream API - Signavio Tech Blog
October 7, 2018 - Person a = new Person(1, "alpha"); Person b = new Person(2, "beta"); List<Person> people = Arrays.asList(a, a, b); Map<Integer, String> idToName = people.stream() .collect(Collectors.toMap(Person::getId, Person::getName)); We get an IllegalStateException saying we have a duplicate key (which is true). Exception in thread "main" java.lang.IllegalStateException: Duplicate key alpha at java.util.stream.Collectors.lambda$throwingMerger$113(Collectors.java:133) at java.util.stream.Collectors$$Lambda$3/764977973.apply(Unknown Source) at java.util.HashMap.merge(HashMap.java:1245) at java.util.stream.
🌐
Mkyong
mkyong.com › home › java8 › java 8 – convert list to map
Java 8 – Convert List to Map | mkyong.com
May 26, 2017 - 2.2 To solve the duplicated key issue above, pass in the third mergeFunction argument like this : Map<String, Long> result1 = list.stream().collect( Collectors.toMap(Hosting::getName, Hosting::getWebsites, (oldValue, newValue) -> oldValue ) ); ... ...
🌐
sqlpey
sqlpey.com › java › java-streams-list-to-map-solutions
Java Streams: Effective Methods to Convert List to Map Using Collectors
November 4, 2025 - String array[] = {"ASDFASDFASDF", "AA", "BBB", "CCCC", "DD", "EEDDDAD"}; List<String> list = Arrays.asList(array); Map<Integer, String> mapByLengthReversed = list.stream() .collect(Collectors.toMap( String::length, // Key Mapper (Length of string) s -> s, // Value Mapper (The string itself) (oldVal, newVal) -> { // Merge Function: Keeps old value, logs collision System.out.println("Duplicate key encountered: " + oldVal); return oldVal; }, () -> new TreeMap<>((s1, s2) -> s2.compareTo(s1)) // Map Supplier: Reverse sorted TreeMap )); // Output for the example data might show a message for "AA" and "DD" if lengths collide.
Top answer
1 of 4
2

As mentioned in the comment, maps do not store duplicated keys so you have to use Map<String, List<String>> instead Map<String, String>.

To sum up, you just have to use Collectors.toMap method with mergeFunction parameter where you can handle duplicated keys. This operation will be called every time when same keys appears. In this case, we simply merge two lists to one. Have a look at below code (compiled with JDK 11), I believe it does exactly what you need and prints an expected result (using List<String> of course).

import java.util.*;
import java.util.stream.Collectors;

public class ListToMapWithDuplicatedKeysSample {

    public static void main(String[] args) {
        List<Address> addresses = List.of(
                new Address("City1", "country1", "state1"),
                new Address("City1", "country1", "state2"),
                new Address("City1", "country1", "state1"),
                new Address("City3", "country3", "state3")
        );
        Map<String, List<String>> result = addresses.stream()
                .collect(
                        Collectors.toMap(
                                address -> address.getCity() + address.getCountry(),
                                address -> Collections.singletonList(address.getState()),
                                ListToMapWithDuplicatedKeysSample::mergeEntriesWithDuplicatedKeys
                        )
                );
        System.out.println(result);
    }

    private static List<String> mergeEntriesWithDuplicatedKeys(List<String> existingResults, List<String> newResults) {
        List<String> mergedResults = new ArrayList<>();
        mergedResults.addAll(existingResults);
        mergedResults.addAll(newResults);
        return mergedResults;
    }

    private static class Address {

        private final String city;
        private final String country;
        private final String state;

        public Address(String city, String country, String state) {
            this.city = city;
            this.country = country;
            this.state = state;
        }

        String getState() {
            return state;
        }

        String getCountry() {
            return country;
        }

        String getCity() {
            return city;
        }
    }
}
2 of 4
2

You can’t use Collectors.toMap, because it requires unique keys. What you want instead is groupingBy, which returns collected values for each key:

class Location {
    public final String city;
    public final String country;

    Location(Address address) {
        this.city = address.getCity();
        this.country = address.getCountry();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Location) {
            Location other = (Location) obj;
            return Objects.equals(this.city, other.city) &&
                   Objects.equals(this.country, other.country);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return Objects.hash(city, country);
    }
}

Map<Location, Set<String>> statesByLocation = addresses.stream().collect(
    Collectors.groupingBy(Location::new,
        Collectors.mapping(Address::getState, Collectors.toSet())));

You could employ various hacks for combining city and country (like a list of two Strings), but you really should just make a key class as shown above. The code will be far easier to work with, especially if you (or another developer) should have a reason to come back to it in six months.

As for the Collector methods:

  • Collectors.groupingBy(Location::new is equivalent to address -> new Location(address) and creates each key in the Map.
  • Collectors.mapping(Address::getState, Collectors.toSet()) means that each Address which corresponds to a particular key will have getState() invoked on it, and the resulting strings will be aggregated in a Set to form the Map value.

Personally, I think I would opt for a simple for-loop instead of the hard-to-read Stream approach:

Map<Location, Set<String>> statesByLocation = new HashMap<>();
for (Address address : addresses) {
    statesByLocation.computeIfAbsent(new Location(address),
        k -> new HashSet<String>()).add(address.getState());
}
🌐
Baeldung
baeldung.com › home › java › java collections › java map › java collectors tomap
Java Collectors toMap | Baeldung
February 26, 2026 - With toMap, we can indicate strategies for how to get the key and value for the map: public Map<String, String> listToMap(List<Book> books) { return books.stream().collect(Collectors.toMap(Book::getIsbn, Book::getName)); } ... @Test public void whenConvertFromListToMap() { assertTrue(convertToMap.listToMap(bookList).size() == 3); } The example above worked well, but what would happen with a duplicate key?
🌐
Java Code Geeks
javacodegeeks.com › home › core java
Flatten a Stream of Maps to a Single Map in Java - Java Code Geeks
May 8, 2024 - line 27: Create a mergeFunction to select the value when duplicate keys are encountered. line 30: Use the mergeFunction when calling Collectors.toMap method, this will handle the duplcate keys map data.
🌐
CodingTechRoom
codingtechroom.com › tutorial › java-java-duplicate-keys-stream-map
Handling Duplicate Keys When Producing Map Using Stream in Java - CodingTechRoom
Explore other Stream operations like flatMap and filter ... Q. Can I use `Collectors.toMap()` without a merge function? A. No, if there are duplicate keys and no merge function, `toMap()` will throw an `IllegalStateException`. Q. What if I want to store values as a List instead of overwriting them? A. You can use `Collectors.groupingBy()` to group values into lists instead of overriding them. ... A broad desk reference for the Java language and standard library.
🌐
Javaprogramto
javaprogramto.com › 2020 › 12 › java-8-stream-convert-list-to-map.html
Java 8 Stream - Convert List to Map
December 10, 2020 - In this article, We've seen how to collect the List to Map using java 8 Streams method Collectors.toMap() method. And alos seen how to handle the duplicate keys with toMap() method and its solution.