Collectors.toMap() – Collect a stream to a map

 197 total views,  1 views today

Welcome to Java 8 series. In this tutorial, you will learn about how to collect a stream to a map using Collectors.toMap().

If you would like to learn more about Java Stream operations.Please check out this link.

In this example, we will use Stream.collect() operation to perform a reduce operation on the stream of elements.i.e., in this case,we will collect a stream of elements to a map using Collectors.toMap().

To use Collectors.toMap() in stream operations, we have to import the Collectors package.

java.util.stream.Collectors

In order to accumulate the elements in a map,we have to first from key and value.

public static <T,K,U> Collector<T,?,Map<K,U>> toMap(
		Function<? super T,? extends K> keyMapper,
                Function<? super T,? extends U> valueMapper)

We have to implement KeyMapper and ValueMapper functions.

  • KeyMapper allows us to provide a function to be applied to the element to identify the key
  • ValueMapper allows us to provide a function to be applied to the element to identify the value

Now let us see a few examples.

Collectors.toMap() examples

1. Consider the element “apple” in that Stream, and I want apple to be stored in a map as (apple,apple). I.e key as apple and value as apple.

Let us see an example of this case.

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

public class StaticReference {
	public static void main(String[] args) {

		List<String> fruits = Arrays.asList("apple", 
				"mango", 
				"pomo", 
				"banana", 
				"orange");

		Map<String, String> collectedFruits = fruits
				.stream()
				.collect(Collectors.toMap
					(item -> item, item -> item));

		collectedFruits.forEach((key, value) -> {
			System.out.println("(" + key + "," + value + ")");
		});

	}
}

Output

(orange,orange)
(banana,banana)
(apple,apple)
(pomo,pomo)
(mango,mango)

2. Consider the element “apple” in that Stream, and I want “apple” to be stored in a map as (apple,uppercase of apple). I.e key as apple and value as APPLE.

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

public class StaticReference {
	public static void main(String[] args) {

		List<String> fruits = Arrays.asList("apple", 
				"mango", 
				"pomo", 
				"banana", 
				"orange");

		Map<String, String> collectedFruits = fruits
				.stream()
				.collect(Collectors.toMap(item -> item, item -> item.toUpperCase()));

		collectedFruits.forEach((key, value) -> {
			System.out.println("(" + key + "," + value + ")");
		});

	}
}

Output

(orange,ORANGE)
(banana,BANANA)
(apple,APPLE)
(pomo,POMO)
(mango,MANGO)

Handling duplicate elements in Collections.toMap()

Consider we have a list that has duplicate values and you are trying to collect it in a map using Collectors.toMap.

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

public class StaticReference
{
    public static void main(String[] args)
    {

        List<String> fruits = Arrays.asList("apple", 
                "mango", "pomo", "banana", "orange", "apple");

        Map<String, String> collectedFruits = fruits
                            .stream()
                            .collect(Collectors.toMap(eachFruit -> eachFruit, eachFruit -> eachFruit));

        collectedFruits.forEach((key, value) -> {
            System.out.println("(" + key + "," + value + ")");
        });

    }
}

Output

Exception in thread "main" java.lang.IllegalStateException: Duplicate key apple

To overcome this issue, we have to use another signature of the Collector.toMap operation that accepts the third argument which handles collision. We have to pass another BinaryOperator function to determine which value to be used during duplicate values. This function is called a merge function.

In our case, I am going to always return the first value.

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

public class StaticReference
{
    public static void main(String[] args)
    {

        List<String> fruits = Arrays.asList("apple", 
                  "mango", 
                  "pomo", 
                  "banana", 
                  "orange", 
                  "apple");

        Map<String, String> collectedFruits = fruits
                 .stream()
                 .collect(Collectors.toMap(
                         eachFruit -> eachFruit, 
                         eachFruit -> eachFruit, 
                         (first, second) -> first));

        collectedFruits.forEach((key, value) -> {
            System.out.println("(" + key + "," + value + ")");
        });

    }
}

Output

Output

(orange,orange)
(banana,banana)
(apple,apple)
(pomo,pomo)
(mango,mango)

I hope you like this article. Thanks for reading and Please leave us a comment below!

Tags :

About the Author

Rajasekar

Hey There, My name is Rajasekar and I am the author of this site. I hope you are liking my tutorials and references. Programming and learning new technologies are my passion. The ultimate idea of this site is to share my knowledge(I am still a learner :)) and help you out!. Please spread your words about us (staticreference.com) and give a thumbs up :) Feel free to contact me for any queries!.