Search code examples
javajava-stream

Map<String, Long> to Map<String, Boolean> if long is > X with Stream


I am looking for a Stream Function to get a Map<String, Boolean> from Map<String, Long>. if the Long is greater than value X, it should be true, otherwise false. Long acts as counter in this case.

Without stream, I figured out this works:

import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Main {
public static void main(String[] args) {
    String[] cars = {"Audi A4", "VW Golf", "Nissan GTR", "Audi A4", "Mercedes Benz C63 AMG", "Skoda Octavia", "Mercedes Benz C63 AMG", "Nissan GTR", "VW Polo", "Nissan GTR"};
    
    // count the occurences of a string in the array to a map
    Map<String, Long> carsOccurences = Stream.of(cars).collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
    
    Map<String, Boolean> moreThanTwoCars = new HashMap<>();
    
    //if a string occures more than 1 time, put true else put false
    for(Map.Entry<String, Long> entry : carsOccurences.entrySet()) {
        if(entry.getValue() > 1)
        moreThanTwoCars.put(entry.getKey(), true);
        else
        moreThanTwoCars.put(entry.getKey(), false);
    }

Is there any way to do the for-loop with a Stream? Maybe even without the Map<String, Integer> but directly from the String-Array. Thanks in advance.


Solution

  • You can use a stream, but it won't be much cleaner. I'd just simplify the loop a little:

    carsOccurences.forEach((key, value) -> moreThanTwoCars.put(key, value > 1));
    

    Alternatively, if you have Guava you can use Maps.transformValues():

    Map<String, Boolean> moreThanTwoCars = Maps.transformValues(carsOccurences, v -> v > 1);
    

    Note that the latter doesn't reconstruct the full map. It's just a view that delegates to the original map and converts values on the fly. But you can always pass it into a new HashMap<>(...) if you need them separated.