Java8: HashMap to HashMap using Stream / Map-Reduce / Collector

前端 未结 9 2141
无人及你
无人及你 2020-11-30 18:38

I know how to \"transform\" a simple Java List from Y -> Z, i.e.:

List x;
List y = x.stre         


        
9条回答
  •  心在旅途
    2020-11-30 18:55

    Here are some variations on Sotirios Delimanolis' answer, which was pretty good to begin with (+1). Consider the following:

    static  Map transform(Map input,
                                         Function function) {
        return input.keySet().stream()
            .collect(Collectors.toMap(Function.identity(),
                                      key -> function.apply(input.get(key))));
    }
    

    A couple points here. First is the use of wildcards in the generics; this makes the function somewhat more flexible. A wildcard would be necessary if, for example, you wanted the output map to have a key that's a superclass of the input map's key:

    Map input = new HashMap();
    input.put("string1", "42");
    input.put("string2", "41");
    Map output = transform(input, Integer::parseInt);
    

    (There is also an example for the map's values, but it's really contrived, and I admit that having the bounded wildcard for Y only helps in edge cases.)

    A second point is that instead of running the stream over the input map's entrySet, I ran it over the keySet. This makes the code a little cleaner, I think, at the cost of having to fetch values out of the map instead of from the map entry. Incidentally, I initially had key -> key as the first argument to toMap() and this failed with a type inference error for some reason. Changing it to (X key) -> key worked, as did Function.identity().

    Still another variation is as follows:

    static  Map transform1(Map input,
                                          Function function) {
        Map result = new HashMap<>();
        input.forEach((k, v) -> result.put(k, function.apply(v)));
        return result;
    }
    

    This uses Map.forEach() instead of streams. This is even simpler, I think, because it dispenses with the collectors, which are somewhat clumsy to use with maps. The reason is that Map.forEach() gives the key and value as separate parameters, whereas the stream has only one value -- and you have to choose whether to use the key or the map entry as that value. On the minus side, this lacks the rich, streamy goodness of the other approaches. :-)

提交回复
热议问题