Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Collect stream into a HashMap with Lambda in Java 8

I have a HashMap which I need to filter using some function:

HashMap<Set<Integer>, Double> container
Map.Entry<Set<Integer>, Double> map = container.entrySet()
            .stream()
            .filter(k -> k.getKey().size() == size)

For the size = 2 the following should be valid:

containerBeforeFilter = {1,2,3} -> 1.5, {1,2} -> 1.3
containerAfterFilter = {1,2} -> 1.3

After I applied the function in the filter, I want to collect results again into a HashMap. However, when I try to apply the method suggested here, I'm getting illegal statements.

So the following statement, applied after the filter, is illegal:

.collect(Collectors.toMap((entry) -> entry.getKey(), (entry) -> entry.getValue()));

What would be the proper way of collecting unchanged map values, where the only criteria is satisfying some key?

UPDATE

The mistake in the above code is the declared type of the variable map. It should have been Map rather than Map.Entry.

So the now functional code is:

Map<Set<Integer>, Double> map = container.entrySet()
            .stream()
            .filter(k -> k.getKey().size() == size)
            .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue()));
like image 688
chao Avatar asked Nov 09 '15 09:11

chao


People also ask

How do I collect a stream map?

Method 1: Using Collectors.toMap() Function The Collectors. toMap() method takes two parameters as the input: KeyMapper: This function is used for extracting keys of the Map from stream value. ValueMapper: This function used for extracting the values of the map for the given key.

Can we use map stream in Java 8?

Java 8 Stream's map method is intermediate operation and consumes single element forom input Stream and produces single element to output Stream. It simply used to convert Stream of one type to another. Let's see method signature of Stream's map method.

Can we use stream on map?

Converting only the Value of the Map<Key, Value> into Stream: This can be done with the help of Map. values() method which returns a Set view of the values contained in this map. In Java 8, this returned set can be easily converted into a Stream of key-value pairs using Set. stream() method.


2 Answers

If your ending map has a chance of "duplicate keys", there is a better solution using

toMap(Function<? super T, ? extends K> keyMapper,                             Function<? super T, ? extends U> valueMapper,                             BinaryOperator<U> mergeFunction,                             Supplier<M> mapSupplier) 

You could use it like this:

HashMap<Set<Integer>, Double> map = container.entrySet()     .stream()     .filter(k -> k.getKey().size() == size)     .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (prev, next) -> next, HashMap::new)); 

Then as duplicate keys are added, it will use the latest instead of throwing an exception. The last parameter is optional.

If you want to keep duplicate keys into a list, then use Collectors.groupingBy instead.

like image 153
provisota Avatar answered Sep 27 '22 18:09

provisota


Seems that Collectors.toMap does not pick up the type arguments of stream.collect in your example and only returns a Map<Object,Object>.

As a workaround you can create the result map yourself and in the last stream step add the filtered entries to the result map:

Map<Set<Integer>, Double> result = new HashMap<>(); container.entrySet()     .stream()     .filter(entry -> entry.getKey().size() == size)     .forEach(entry -> result.put(entry.getKey(), entry.getValue())); 
like image 23
wero Avatar answered Sep 27 '22 18:09

wero