有没有一种优雅的方法可以将地图流减少到一个地图

Boh*_*ian 10 java reduce lambda java-8

鉴于一些地图,有没有一种单行方式将所有条目放入一张地图?

忽略空值,覆盖条目等问题,我想编码的是:

public static <K, V> Map<K, V> reduce(Map<K, V>... maps) {
    return Arrays.stream(maps)
        .reduce(new HashMap<K, V>(), (a, b) -> a.putAll(b));
}
Run Code Online (Sandbox Code Playgroud)

但这会产生编译错误,因为a.putAll(b)void.如果它返回this,它会工作.

为了解决这个问题,我编码:

public static <K, V> Map<K, V> reduce(Map<K, V>... maps) {
    return Arrays.stream(maps)
        .reduce(new HashMap<K, V>(), (a, b) -> {a.putAll(b); return a;});
}
Run Code Online (Sandbox Code Playgroud)

它编译和工作,但它是一个丑陋的lambda; 编码return a;感觉多余.

一种方法是重构一个实用方法:

public static <K, V> Map<K, V> reduce(Map<K, V> a, Map<K, V> b) {
    a.putAll(b);
    return a;
}
Run Code Online (Sandbox Code Playgroud)

清理lambda:

public static <K, V> Map<K, V> reduce(Map<K, V>... maps) {
    return Arrays.stream(maps)
       .reduce(new HashMap<K, V>(), (a, b) -> reduce(a, b));
}
Run Code Online (Sandbox Code Playgroud)

但是现在我有了一个虽然可重复使用但有些无用的实用方法.

是否有更优雅的方法在累加器上调用方法在lambda中返回它?

Psh*_*emo 15

reduce 与...类似

U result = identity;
for (T element : this stream)
    result = accumulator.apply(result, element)
return result;
Run Code Online (Sandbox Code Playgroud)

这意味着代表accumulator.apply需要的lambda return(最终或中间的).

如果你想避免这种行为使用collect哪个更像

R result = supplier.get();
for (T element : this stream)
    accumulator.accept(result, element);
return result;
Run Code Online (Sandbox Code Playgroud)

所以lambda表示accumulator.accept不需要return任何值,而是result基于修改element.

例:

public static <K, V> Map<K, V> reduce(Map<K, V>... maps) {
    return Arrays.stream(maps)
            .collect(HashMap::new, Map::putAll, Map::putAll);
            //                          ^            ^
            //                          |         collect results from parallel streams
            //                       collect results in single thread
}
Run Code Online (Sandbox Code Playgroud)

  • @Bohemian:减少是完全可并行化的,只要你的缩减函数是*associative*.`reduce`和`collect`之间的区别在于`reduce`通过消耗*值*并产生新*值*(想想sum,max,min)来工作,而`collect`通过将元素合并到一个可变结果容器中来工作(列表,集,地图,数组等) (2认同)