Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I keep the iteration order of a List when using Collections.toMap() on a stream?

I am creating a Map from a List as follows:

List<String> strings = Arrays.asList("a", "bb", "ccc");  Map<String, Integer> map = strings.stream()     .collect(Collectors.toMap(Function.identity(), String::length)); 

I want to keep the same iteration order as was in the List. How can I create a LinkedHashMap using the Collectors.toMap() methods?

like image 967
Ashika Umanga Umagiliya Avatar asked Mar 17 '15 02:03

Ashika Umanga Umagiliya


People also ask

Does List stream maintain order?

List , its stream() method will return an ordered stream and filter will not change the ordering. So if you call list. stream().

What is Encounter order in streams?

Simply put, encounter order is the order in which a Stream encounters data.

Does Flatmap preserve order?

Does flatmap() method preserve the order of the streams? Yes, It does and map() also.

When performing operations on a stream will it affect the original stream?

A stream can be composed of multiple functions that create a pipeline that data that flows through. This data cannot be mutated. That is to say the original data structure doesn't change. However the data can be transformed and later stored in another data structure or perhaps consumed by another operation.


2 Answers

The 2-parameter version of Collectors.toMap() uses a HashMap:

public static <T, K, U> Collector<T, ?, Map<K,U>> toMap(     Function<? super T, ? extends K> keyMapper,      Function<? super T, ? extends U> valueMapper)  {     return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new); } 

To use the 4-parameter version, you can replace:

Collectors.toMap(Function.identity(), String::length) 

with:

Collectors.toMap(     Function.identity(),      String::length,      (u, v) -> {         throw new IllegalStateException(String.format("Duplicate key %s", u));     },      LinkedHashMap::new ) 

Or to make it a bit cleaner, write a new toLinkedMap() method and use that:

public class MoreCollectors {     public static <T, K, U> Collector<T, ?, Map<K,U>> toLinkedMap(         Function<? super T, ? extends K> keyMapper,         Function<? super T, ? extends U> valueMapper)     {         return Collectors.toMap(             keyMapper,             valueMapper,              (u, v) -> {                 throw new IllegalStateException(String.format("Duplicate key %s", u));             },             LinkedHashMap::new         );     } } 
like image 74
prunge Avatar answered Sep 23 '22 21:09

prunge


Make your own Supplier, Accumulator and Combiner:

List<String> myList = Arrays.asList("a", "bb", "ccc");  // or since java 9 List.of("a", "bb", "ccc");      LinkedHashMap<String, Integer> mapInOrder = myList                         .stream()                         .collect(                           LinkedHashMap::new,                           // Supplier                           (map, item) -> map.put(item, item.length()),  // Accumulator                           Map::putAll);                                 // Combiner  System.out.println(mapInOrder);  // prints {a=1, bb=2, ccc=3} 
like image 34
hzitoun Avatar answered Sep 25 '22 21:09

hzitoun