Java Collectors toMap() Method

The toMap() method in Java, part of the java.util.stream.Collectors class, is used to collect elements of a stream into a Map. This method is useful when you need to create a map from a collection of elements by specifying how to derive the keys and values.

Table of Contents

  1. Introduction
  2. toMap() Method Syntax
  3. Understanding toMap()
  4. Examples
    • Basic Usage
    • Using toMap() with Custom Objects
    • Handling Duplicate Keys with Merge Function
  5. Real-World Use Case
  6. Conclusion

Introduction

The toMap() method returns a Collector that accumulates elements into a Map whose keys and values are the result of applying a key mapping and value mapping function, respectively. There are multiple overloaded versions of this method to provide flexibility in how the map is constructed.

toMap() Method Syntax

There are three overloaded versions of the toMap() method:

  1. Basic toMap() method with key and value mappers:
public static <T, K, U> Collector<T, ?, Map<K, U>> toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper)
  1. toMap() method with key and value mappers and a merge function:
public static <T, K, U> Collector<T, ?, Map<K, U>> toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper, BinaryOperator<U> mergeFunction)
  1. toMap() method with key and value mappers, a merge function, and a map supplier:
public static <T, K, U, M extends Map<K, U>> Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier)

Parameters:

  • keyMapper: A function that maps the input elements to keys.
  • valueMapper: A function that maps the input elements to values.
  • mergeFunction (optional): A binary operator used to resolve collisions between values associated with the same key.
  • mapSupplier (optional): A supplier providing a new empty Map into which the results will be inserted.

Returns:

  • A Collector that accumulates the input elements into a Map.

Throws:

  • This method may throw IllegalStateException if duplicate keys are encountered and no merge function is provided.

Understanding toMap()

The toMap() method allows you to collect the elements of a stream into a map. This is useful in scenarios where you need to create a map from a collection of elements by specifying how to derive the keys and values.

Examples

Basic Usage

To demonstrate the basic usage of toMap(), we will create a stream of strings and collect them into a Map with the string as the key and its length as the value.

Example

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class ToMapExample {
    public static void main(String[] args) {
        List<String> words = Arrays.asList("apple", "banana", "cherry", "date");

        // Collect the words into a Map with the word as the key and its length as the value
        Map<String, Integer> wordLengthMap = words.stream()
                                                  .collect(Collectors.toMap(
                                                      word -> word,
                                                      String::length
                                                  ));

        System.out.println("Word Length Map: " + wordLengthMap);
    }
}

Output:

Word Length Map: {banana=6, date=4, apple=5, cherry=6}

Using toMap() with Custom Objects

This example shows how to use toMap() with a stream of custom objects to collect them into a map.

Example

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class ToMapCustomObjectExample {
    static class Product {
        String name;
        double price;

        Product(String name, double price) {
            this.name = name;
            this.price = price;
        }

        String getName() {
            return name;
        }

        double getPrice() {
            return price;
        }
    }

    public static void main(String[] args) {
        List<Product> products = Arrays.asList(
            new Product("Product A", 10.0),
            new Product("Product B", 20.5),
            new Product("Product C", 15.8)
        );

        // Collect the products into a Map with the product name as the key and price as the value
        Map<String, Double> productPriceMap = products.stream()
                                                      .collect(Collectors.toMap(
                                                          Product::getName,
                                                          Product::getPrice
                                                      ));

        System.out.println("Product Price Map: " + productPriceMap);
    }
}

Output:

Product Price Map: {Product A=10.0, Product B=20.5, Product C=15.8}

Handling Duplicate Keys with Merge Function

This example shows how to use toMap() with a merge function to handle collisions between values associated with the same key.

Example

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class MergeFunctionExample {
    public static void main(String[] args) {
        List<String> words = Arrays.asList("apple", "banana", "cherry", "apricot");

        // Collect the words into a Map with the first letter as the key and concatenated words as the value
        Map<Character, String> wordMap = words.stream()
                                              .collect(Collectors.toMap(
                                                  word -> word.charAt(0),
                                                  word -> word,
                                                  (existing, replacement) -> existing + ", " + replacement
                                              ));

        System.out.println("Word Map: " + wordMap);
    }
}

Output:

Word Map: {a=apple, apricot, b=banana, c=cherry}

Real-World Use Case

Grouping Employees by Department

In real-world applications, the toMap() method can be used to collect employees into a map based on their department.

Example

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class EmployeeDepartmentExample {
    static class Employee {
        String name;
        String department;

        Employee(String name, String department) {
            this.name = name;
            this.department = department;
        }

        String getName() {
            return name;
        }

        String getDepartment() {
            return department;
        }
    }

    public static void main(String[] args) {
        List<Employee> employees = Arrays.asList(
            new Employee("Alice", "HR"),
            new Employee("Bob", "IT"),
            new Employee("Charlie", "HR"),
            new Employee("David", "Finance")
        );

        // Collect the employees into a Map with the department as the key and names as the value
        Map<String, String> departmentMap = employees.stream()
                                                     .collect(Collectors.toMap(
                                                         Employee::getDepartment,
                                                         Employee::getName,
                                                         (existing, replacement) -> existing + ", " + replacement
                                                     ));

        System.out.println("Department Map: " + departmentMap);
    }
}

Output:

Department Map: {Finance=David, HR=Alice, Charlie, IT=Bob}

Conclusion

The Collectors.toMap() method is used to collect elements of a stream into a Map. This method is particularly useful for creating maps from streams of data by specifying how to derive the keys and values. By understanding and using this method, you can efficiently manage mapping operations in your Java applications.

Comments