Convert Java Stream to Map
October 13, 2020
On this page we will learn how to convert Java Stream
to Map
. Java Stream.collect
performs a mutable reduction operation on the elements using a Collector
.
<R,A> R collect(Collector<? super T,A,R> collector)
Map
, we need to pass Collector
as argument achieved by calling following methods.
1.
Collectors.toMap
2.
Collectors.toConcurrentMap
3.
Collectors.toUnmodifiableMap
4.
Collectors.groupingBy
Now let us discuss the use of above methods to convert stream into map.
Contents
1. Using Collectors.toMap
TheCollectors.toMap
returns a Collector
that accumulates elements into a Map
whose keys and values are obtained by provided mapping functions to the input elements. It has following variants.
a. If the keys are duplicates, an
IllegalStateException
is thrown when the collection operation is performed.
public static <T,K,U> Collector<T,?,Map<K,U>> toMap( Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper)
ExampleToMap1.java
package com.concretepage; import java.util.Arrays; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; public class ExampleToMap1 { public static void main(String[] args) { Map<Integer, Integer> map1 = Stream.of(10, 15, 20) .collect(Collectors.toMap(i -> i, i -> i * 2)); System.out.println(map1); Map<Integer, Integer> map2 = IntStream.range(20, 25).boxed() .collect(Collectors.toMap(i -> i + 2, i -> i * 5)); System.out.println(map2); Map<Integer, String> map3 = Arrays.asList(1, 2, 3).stream().map(i -> i * 2) .collect(Collectors.toMap(i -> i * 10, i -> "A" + i)); System.out.println(map3); } }
{20=40, 10=20, 15=30} {22=100, 23=105, 24=110, 25=115, 26=120} {20=A2, 40=A4, 60=A6}
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)
ExampleToMap2.java
package com.concretepage; import java.util.Arrays; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; public class ExampleToMap2 { public static void main(String[] args) { Map<Integer, Integer> map1 = Stream.of(10, 10, 15, 20) .collect(Collectors.toMap(i -> i, i -> i * 2, (x, y) -> x + y)); System.out.println(map1); Map<Integer, String> map2 = Arrays.asList(1, 1, 2, 2, 3).stream().map(i -> i * 2) .collect(Collectors.toMap(i -> i * 10, i -> "A" + i, (x, y) -> x + "-" + y)); System.out.println(map2); } }
{20=40, 10=40, 15=30} {20=A2-A2, 40=A4-A4, 60=A6}
Map
is created by provided supplier function.
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> mapFactory)
LinkedHashMap
passing as supplier to retain the sorted value.
ExampleToMap3.java
package com.concretepage; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.Map; import java.util.stream.Collectors; public class ExampleToMap3 { public static void main(String[] args) { Map<Integer, String> map2 = Arrays.asList(15, 10, 10, 20).stream().sorted() .collect(Collectors.toMap(i -> i, i -> "A" + i, (x, y) -> x + "-" + y, LinkedHashMap::new)); System.out.println(map2); } }
{10=A10-A10, 15=A15, 20=A20}
2. Using Collectors.toConcurrentMap
TheCollectors.toConcurrentMap
returns a concurrent Collector
that accumulates elements into a ConcurrentMap
whose keys and values are obtained by provided mapping functions to the input elements.
The
Collectors.toConcurrentMap
uses the same variant of arguments as Collectors.toMap
as following.
(i) keyMapper, valueMapper
(ii) keyMapper, valueMapper, mergeFunction
(iii) keyMapper, valueMapper, mergeFunction, mapFactory
Find the example.
ExampleToConcurrentMap.java
package com.concretepage; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.stream.Collectors; import java.util.stream.Stream; public class ExampleToConcurrentMap { public static void main(String[] args) { ConcurrentMap<Integer, Integer> map1 = Stream.of(10, 15, 20) .collect(Collectors.toConcurrentMap(i -> i, i -> i * 2)); System.out.println(map1); ConcurrentMap<Integer, String> map2 = Stream.of(1, 2, 2, 3, 3) .collect(Collectors.toConcurrentMap(i -> i * 10, i -> "A" + i, (x, y) -> x + "-" + y)); System.out.println(map2); ConcurrentMap<Integer, String> map3 = Stream.of(15, 10, 10, 20) .collect(Collectors.toConcurrentMap(i -> i, i -> "A" + i, (x, y) -> x + "-" + y, ConcurrentHashMap::new)); System.out.println(map3); } }
{20=40, 10=20, 15=30} {20=A2-A2, 10=A1, 30=A3-A3} {20=A20, 10=A10-A10, 15=A15}
3. Using Collectors.toUnmodifiableMap
TheCollectors.toUnmodifiableMap
returns a Collector
that accumulates elements into an unmodifiable Map
whose keys and values are obtained by provided mapping functions to the input elements. To handle duplicate keys we can pass mergeFunction in the same way as in Collectors.toMap
. The Collectors.toUnmodifiableMap
can accept following variant of arguments.
(i) keyMapper, valueMapper
(ii) keyMapper, valueMapper, mergeFunction
Example:
ExampleToUnmodifiableMap.java
package com.concretepage; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; public class ExampleToUnmodifiableMap { public static void main(String[] args) { Map<Integer, Integer> map1 = Stream.of(10, 15, 20) .collect(Collectors.toUnmodifiableMap(i -> i, i -> i * 2)); System.out.println(map1); Map<Integer, String> map2 = Stream.of(1, 1, 2, 2, 3).map(i -> i * 2) .collect(Collectors.toUnmodifiableMap(i -> i * 10, i -> "A" + i, (x, y) -> x + "-" + y)); System.out.println(map2); } }
{20=40, 15=30, 10=20} {20=A2-A2, 40=A4-A4, 60=A6}
4. Using Collectors.groupingBy
TheCollectors.groupingBy
returns a Collector
implementing a "group by" operation on input elements for a type and groups elements according to a classification function and returns result as Map
.
Find the
Collectors.groupingBy
method declaration from Java doc.
public static <T,K> Collector<T,?,Map<K,List<T>>> groupingBy(Function<? super T,? extends K> classifier)
ExampleGroupingBy.java
package com.concretepage; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; public class ExampleGroupingBy { public static void main(String[] args) { Person p1 = new Person(20, "Mahesh"); Person p2 = new Person(25, "Krishn"); Person p3 = new Person(20, "Nilesh"); Person p4 = new Person(25, "Bharat"); Map<Integer, List<Person>> personByAge = Stream.of(p1, p2, p3, p4) .collect(Collectors.groupingBy(Person::getAge)); System.out.println(personByAge); } } class Person { private int age; private String name; public Person(int age, String name) { this.age = age; this.name = name; } //Sets, Gets @Override public String toString() { return age + "-" + name; } }
{20=[20-Mahesh, 20-Nilesh], 25=[25-Krishn, 25-Bharat]}
5. References
StreamCollectors