From 9538041ac548f8588900ec4db819c39690dd00b7 Mon Sep 17 00:00:00 2001 From: achao Date: Sun, 3 Jul 2022 17:35:54 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=A4=84=E7=90=86Collectors=E9=81=87?= =?UTF-8?q?=E5=88=B0null=E7=9A=84=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/cn/hutool/core/stream/CollectorUtil.java | 7 ++++++- .../java/cn/hutool/core/collection/CollStreamUtilTest.java | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) 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 1d264e744..28eb6b774 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 @@ -2,6 +2,7 @@ package cn.hutool.core.stream; import cn.hutool.core.lang.Opt; import cn.hutool.core.text.StrUtil; +import cn.hutool.core.util.ArrayUtil; import java.util.Collections; import java.util.EnumSet; @@ -9,6 +10,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.List; +import java.util.Objects; import java.util.StringJoiner; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; @@ -104,7 +106,10 @@ public class CollectorUtil { final BiConsumer, T> accumulator = (m, t) -> { final K key = Opt.ofNullable(t).map(classifier).orElse(null); final A container = m.computeIfAbsent(key, k -> downstreamSupplier.get()); - downstreamAccumulator.accept(container, t); + if (ArrayUtil.isArray(container) || Objects.nonNull(t)) { + // 如果是数组类型,不需要判空,场景——分组后需要使用:java.util.stream.Collectors.counting 求null元素个数 + downstreamAccumulator.accept(container, t); + } }; final BinaryOperator> merger = mapMerger(downstream.combiner()); @SuppressWarnings("unchecked") final Supplier> mangledFactory = (Supplier>) mapFactory; diff --git a/hutool-core/src/test/java/cn/hutool/core/collection/CollStreamUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/collection/CollStreamUtilTest.java index c1d5a2786..f3d1b883c 100644 --- a/hutool-core/src/test/java/cn/hutool/core/collection/CollStreamUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/CollStreamUtilTest.java @@ -153,7 +153,7 @@ public class CollStreamUtilTest { // 对null友好 final Map> termIdClassIdStudentMap = CollStreamUtil.group2Map(Arrays.asList(null, new Student(2, 2, 1, "王五")), Student::getTermId, Student::getClassId); final Map> termIdClassIdStudentCompareMap = new HashMap>() {{ - put(null, MapUtil.of(null, null)); + put(null, MapUtil.empty()); put(2L, MapUtil.of(2L, new Student(2, 2, 1, "王五"))); }}; Assert.assertEquals(termIdClassIdStudentCompareMap, termIdClassIdStudentMap); @@ -215,7 +215,7 @@ public class CollStreamUtilTest { new Student(1, 2, 1, "李四")); final Map> termIdStudentsMap = CollStreamUtil.groupBy(students, Student::getTermId, Collectors.toList()); final Map> termIdStudentsCompareMap = new HashMap<>(); - termIdStudentsCompareMap.put(null, Arrays.asList(null, null)); + termIdStudentsCompareMap.put(null, Collections.emptyList()); termIdStudentsCompareMap.put(1L, Arrays.asList(new Student(1L, 1, 1, "张三"), new Student(1L, 2, 1, "李四"))); Assert.assertEquals(termIdStudentsCompareMap, termIdStudentsMap); From 26cf1ba18fb27e4a728c00d41464c414f1aab9cd Mon Sep 17 00:00:00 2001 From: achao Date: Sun, 3 Jul 2022 19:05:57 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=96=B0=E5=A2=9ECollectorUtil.reduceListM?= =?UTF-8?q?ap()=EF=BC=8C=E7=94=A8=E4=BA=8E=E8=81=9A=E5=90=88=E9=9B=86?= =?UTF-8?q?=E5=90=88=E4=B8=AD=E7=9A=84=20=E6=AF=8F=E4=B8=80=E4=B8=AAmap=20?= =?UTF-8?q?=E4=B8=BA=E4=B8=80=E4=B8=AA=E5=A4=A7map=20Collection>?= =?UTF-8?q?=20=3D>=20Map>?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/hutool/core/stream/CollectorUtil.java | 35 ++++++++++++++++++ .../hutool/core/stream/CollectorUtilTest.java | 37 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 hutool-core/src/test/java/cn/hutool/core/stream/CollectorUtilTest.java 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); + } +}