diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/CollectorUtil.java b/hutool-core/src/main/java/cn/hutool/core/stream/CollectorUtil.java index 28eb6b774..47102cefd 100644 --- a/hutool-core/src/main/java/cn/hutool/core/stream/CollectorUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/stream/CollectorUtil.java @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.List; +import java.util.ArrayList; import java.util.Objects; import java.util.StringJoiner; import java.util.function.BiConsumer; @@ -216,5 +217,39 @@ public class CollectorUtil { }; } + /** + * 聚合这种数据类型:{@code Collection> => Map>} + * 其中key相同的value,会累加到List中 + * + * @param key的类型 + * @param value的类型 + * @return 聚合后的map + */ + public static Collector, ?, Map>> reduceListMap() { + return reduceListMap(HashMap::new); + } + + /** + * 聚合这种数据类型:{@code Collection> => Map>} + * 其中key相同的value,会累加到List中 + * + * @param mapSupplier 可自定义map的类型如concurrentHashMap等 + * @param key的类型 + * @param value的类型 + * @param 返回值的类型 + * @return 聚合后的map + */ + public static >> Collector, ?, R> reduceListMap(final Supplier mapSupplier) { + return Collectors.reducing(mapSupplier.get(), value -> { + R result = mapSupplier.get(); + value.forEach((k, v) -> result.computeIfAbsent(k, i -> new ArrayList<>()).add(v)); + return result; + }, (l, r) -> { + r.forEach((k, v) -> l.computeIfAbsent(k, i -> new ArrayList<>()).addAll(v)); + return l; + } + ); + } + } diff --git a/hutool-core/src/test/java/cn/hutool/core/stream/CollectorUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/stream/CollectorUtilTest.java new file mode 100644 index 000000000..72e943cf5 --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/stream/CollectorUtilTest.java @@ -0,0 +1,37 @@ +package cn.hutool.core.stream; + +import cn.hutool.core.map.MapUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * CollectorUtilTest + * + * @author VampireAchao + * @since 2022/7/3 + */ +public class CollectorUtilTest { + + @Test + public void reduceListMapTest() { + Set> nameScoreMapList = StreamUtil.of( + // 集合内的第一个map,包含两个key value + MapUtil.builder("苏格拉底", 1).put("特拉叙马霍斯", 3).build(), + MapUtil.of("苏格拉底", 2), + MapUtil.of("特拉叙马霍斯", 1), + MapUtil.of("特拉叙马霍斯", 2) + ).collect(Collectors.toSet()); + // 执行聚合 + Map> nameScoresMap = nameScoreMapList.stream().collect(CollectorUtil.reduceListMap()); + + Assert.assertEquals(MapUtil.builder("苏格拉底", Arrays.asList(1, 2)) + .put("特拉叙马霍斯", Arrays.asList(3, 1, 2)).build(), + nameScoresMap); + } +}