[英]Is there an elegant way to reduce a stream of maps to one map
鑒於一些地圖,有沒有一種單行方式將所有條目放入一張地圖?
忽略空值,覆蓋條目等問題,我想編碼的是:
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));
}
但是這會產生編譯錯誤,因為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;});
}
它編譯和工作,但它是一個丑陋的lambda; 編碼return a;
感到多余。
一種方法是重構一個實用方法:
public static <K, V> Map<K, V> reduce(Map<K, V> a, Map<K, V> b) {
a.putAll(b);
return a;
}
清理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));
}
但是現在我有了一個雖然可重復使用但有些無用的實用方法。
是否有更優雅的方法在累加器上調用方法並在lambda中返回它?
reduce
工作類似於
U result = identity;
for (T element : this stream)
result = accumulator.apply(result, element)
return result;
這意味着表示accumulator.apply
的lambda需要return
結果(final或middle one)。
如果你想避免這種行為,請使用更有效的collect
R result = supplier.get();
for (T element : this stream)
accumulator.accept(result, element);
return result;
所以表示accumulator.accept
lambda不需要return
任何值,而是根據element
修改result
。
例:
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
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.