A logo showing the text blog.marcnuri.com
Español
Home»Backend Development»Java Streams: Convert List into Map

Recent Posts

  • 2025 Year in Review: The Year of AI
  • Synology DS224+: How to upgrade hard drives in RAID 1
  • Fabric8 Kubernetes Client 7.5 is now available!
  • Boosting My Developer Productivity with AI in 2025
  • Black Box vs White Box Testing: When to Use Each Approach

Categories

  • Artificial Intelligence
  • Backend Development
  • Cloud Native
  • Engineering Insights
  • Frontend Development
  • JavaScript
  • Legacy
  • Operations
  • Personal
  • Pet projects
  • Quality Engineering
  • Tools

Archives

  • January 2026
  • December 2025
  • October 2025
  • September 2025
  • July 2025
  • May 2025
  • April 2025
  • March 2025
  • February 2025
  • January 2025
  • December 2024
  • November 2024
  • August 2024
  • June 2024
  • May 2024
  • April 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
  • November 2023
  • October 2023
  • September 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • April 2023
  • March 2023
  • February 2023
  • January 2023
  • December 2022
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • July 2022
  • June 2022
  • May 2022
  • March 2022
  • February 2022
  • January 2022
  • December 2021
  • November 2021
  • October 2021
  • September 2021
  • August 2021
  • July 2021
  • January 2021
  • December 2020
  • November 2020
  • October 2020
  • September 2020
  • August 2020
  • July 2020
  • June 2020
  • May 2020
  • March 2020
  • February 2020
  • January 2020
  • December 2019
  • November 2019
  • October 2019
  • September 2019
  • July 2019
  • March 2019
  • November 2018
  • July 2018
  • June 2018
  • May 2018
  • April 2018
  • March 2018
  • February 2018
  • December 2017
  • October 2017
  • August 2017
  • July 2017
  • January 2017
  • December 2015
  • November 2015
  • December 2014
  • November 2014
  • October 2014
  • March 2014
  • February 2011
  • November 2008
  • June 2008
  • May 2008
  • April 2008
  • January 2008
  • November 2007
  • September 2007
  • August 2007
  • July 2007
  • June 2007
  • May 2007
  • April 2007
  • March 2007

Java Streams: Convert List into Map

2018-03-30 in Backend Development tagged Collector / Java / List / Map / Streams by Marc Nuri | Last updated: 2026-01-27
Versión en Español

Introduction

Converting a List into a Map is one of the most common operations when working with Java Streams. Maps are data structures composed of key-value pairs where each key is unique, allowing for fast lookups without iterating through the entire collection.

In this post, I'll cover everything you need to know about converting a List to a Map using Collectors.toMap():

  • Basic conversion when keys are unique
  • Handling duplicate keys with merge functions
  • Maintaining insertion order with LinkedHashMap
  • Sorting keys with TreeMap
  • Creating immutable maps with toUnmodifiableMap()
  • Handling null values and avoiding NullPointerException

For the examples, I'll use a Repository record:

Repository.java
public record Repository(String name, String fullName, String description, boolean fork) {}

Tip

If you're using a version before Java 16, you can use a traditional class with getters instead.

List to Map with no duplicate keys

When you're certain that the List contains no duplicate keys, use the basic two-argument version of Collectors.toMap().

The following snippet shows the basic conversion:

ListToMapBasic.java
repos.stream().collect(Collectors.toMap(Repository::name, Function.identity()));

The first step 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()). For the Map value, we use Function.identity() which returns the same element (equivalent to r -> r).

Important

If the list contains duplicate keys, this will throw an IllegalStateException. See the next section for handling duplicates.

List to Map with duplicate keys

When the list might contain duplicate keys, use the three-argument version of toMap() that includes a merge function.

The following snippet shows how to handle duplicates:

ListToMapWithDuplicates.java
repos.stream().collect(Collectors.toMap(
    Repository::name,
    Function.identity(),
    (existing, replacement) -> replacement
));

The third parameter is a BinaryOperator that receives both values when a duplicate key is encountered. In this example, we keep the newer value (replacement), but you could:

  • Keep the first value: (existing, replacement) -> existing
  • Combine values: (existing, replacement) -> mergeRepositories(existing, replacement)
  • Throw an exception: (existing, replacement) -> { throw new IllegalStateException("Duplicate key"); }

List to Map preserving insertion order

By default, Collectors.toMap() creates a HashMap, which doesn't preserve insertion order. To maintain the order of elements from the original list, use a LinkedHashMap.

The following snippet shows how to preserve insertion order:

ListToMapOrdered.java
LinkedHashMap<String, Repository> map = repos.stream().collect(Collectors.toMap(
    Repository::name,
    Function.identity(),
    (existing, replacement) -> existing,
    LinkedHashMap::new
));

The fourth parameter is a Supplier that provides the Map implementation. LinkedHashMap maintains a doubly-linked list of entries, preserving the iteration order.

List to Map keeping key ordering

To sort keys alphabetically, use a TreeMap which implements SortedMap.

The following snippet shows how to sort keys:

ListToMapOrdered.java
TreeMap<String, Repository> sorted = repos.stream().collect(Collectors.toMap(
    Repository::name,
    Function.identity(),
    (existing, replacement) -> existing,
    TreeMap::new
));

For reverse alphabetical order, provide a Comparator to the TreeMap constructor:

ListToMapOrdered.java
repos.stream().collect(Collectors.toMap(
    Repository::name,
    Function.identity(),
    (existing, replacement) -> existing,
    () -> new TreeMap<>(Comparator.reverseOrder())
));

Creating immutable maps

Since Java 10, you can use Collectors.toUnmodifiableMap() to create an immutable map directly.

The following snippet shows how to create an immutable map:

ListToMapUnmodifiable.java
Map<String, Repository> immutableMap = repos.stream()
    .collect(Collectors.toUnmodifiableMap(Repository::name, Function.identity()));

Any attempt to modify this map will throw an UnsupportedOperationException. This is useful for creating read-only data structures and ensuring thread safety.

Tip

There's also a version with a merge function for handling duplicate keys: toUnmodifiableMap(keyMapper, valueMapper, mergeFunction).

Handling null values

Warning

Collectors.toMap() throws a NullPointerException when the value mapper returns null. This is because it internally uses HashMap.merge() which doesn't accept null values.

// This throws NullPointerException if description is null!
repos.stream().collect(Collectors.toMap(Repository::name, Repository::description));

There are several workarounds (see ListToMapNullHandling.java for full examples):

Option 1: Use a traditional loop with HashMap.put()

ListToMapNullHandling.java
Map<String, String> map = new HashMap<>();
repos.forEach(repo -> map.put(repo.name(), repo.description()));

Option 2: Replace nulls with a default value

ListToMapNullHandling.java
repos.stream().collect(Collectors.toMap(
    Repository::name,
    repo -> repo.description() != null ? repo.description() : "No description"
));

Option 3: Filter out null values before collecting

ListToMapNullHandling.java
repos.stream()
    .filter(repo -> repo.description() != null)
    .collect(Collectors.toMap(Repository::name, Repository::description));

When to use toMap() vs groupingBy()

Use Collectors.toMap() when:

  • Each element maps to exactly one key-value pair
  • Keys should be unique (or you'll provide a merge function)

Use Collectors.groupingBy() when:

  • Multiple elements share the same key
  • You want a Map<K, List<V>> structure
// groupingBy: groups multiple repositories by the fork flag
Map<Boolean, List<Repository>> byFork = repos.stream()
    .collect(Collectors.groupingBy(Repository::fork));

Conclusion

In this post, I've shown how to convert a List to a Map using Java Streams with Collectors.toMap(). Key takeaways:

  • Use the basic two-argument toMap() for unique keys
  • Add a merge function to handle duplicates
  • Use LinkedHashMap to preserve insertion order
  • Use TreeMap for sorted keys
  • Use toUnmodifiableMap() for immutable maps (Java 10+)
  • Be aware of NullPointerException with null values

You can find the full source code for this article on GitHub.

Java Streams
Java Streams
Twitter iconFacebook iconLinkedIn iconPinterest iconEmail icon

Post navigation
Java 10: Testing the new releaseSpring Data MongoDB Custom repository implementation
© 2007 - 2026 Marc Nuri