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 47102cefd..50911a02d 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 @@ -4,15 +4,7 @@ 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; -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.*; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; import java.util.function.Function; @@ -32,7 +24,7 @@ public class CollectorUtil { * 说明已包含IDENTITY_FINISH特征 为 Characteristics.IDENTITY_FINISH 的缩写 */ public static final Set CH_ID - = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH)); + = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH)); /** * 说明不包含IDENTITY_FINISH特征 */ @@ -58,7 +50,7 @@ public class CollectorUtil { * @return {@link Collector} */ public static Collector joining(final CharSequence delimiter, - final Function toStringFunc) { + final Function toStringFunc) { return joining(delimiter, StrUtil.EMPTY, StrUtil.EMPTY, toStringFunc); } @@ -73,15 +65,15 @@ public class CollectorUtil { * @return {@link Collector} */ public static Collector joining(final CharSequence delimiter, - final CharSequence prefix, - final CharSequence suffix, - final Function toStringFunc) { + final CharSequence prefix, + final CharSequence suffix, + final Function toStringFunc) { return new SimpleCollector<>( - () -> new StringJoiner(delimiter, prefix, suffix), - (joiner, ele) -> joiner.add(toStringFunc.apply(ele)), - StringJoiner::merge, - StringJoiner::toString, - Collections.emptySet() + () -> new StringJoiner(delimiter, prefix, suffix), + (joiner, ele) -> joiner.add(toStringFunc.apply(ele)), + StringJoiner::merge, + StringJoiner::toString, + Collections.emptySet() ); } @@ -100,8 +92,8 @@ public class CollectorUtil { * @return {@link Collector} */ public static > Collector groupingBy(final Function classifier, - final Supplier mapFactory, - final Collector downstream) { + final Supplier mapFactory, + final Collector downstream) { final Supplier downstreamSupplier = downstream.supplier(); final BiConsumer downstreamAccumulator = downstream.accumulator(); final BiConsumer, T> accumulator = (m, t) -> { @@ -141,7 +133,7 @@ public class CollectorUtil { */ public static Collector> groupingBy(final Function classifier, - final Collector downstream) { + final Collector downstream) { return groupingBy(classifier, HashMap::new, downstream); } @@ -171,8 +163,8 @@ public class CollectorUtil { */ public static Collector> toMap(final Function keyMapper, - final Function valueMapper, - final BinaryOperator mergeFunction) { + final Function valueMapper, + final BinaryOperator mergeFunction) { return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new); } @@ -191,11 +183,11 @@ public class CollectorUtil { */ public static > Collector toMap(final Function keyMapper, - final Function valueMapper, - final BinaryOperator mergeFunction, - final Supplier mapSupplier) { + final Function valueMapper, + final BinaryOperator mergeFunction, + final Supplier mapSupplier) { final BiConsumer accumulator - = (map, element) -> map.put(Opt.ofNullable(element).map(keyMapper).get(), Opt.ofNullable(element).map(valueMapper).get()); + = (map, element) -> map.put(Opt.ofNullable(element).map(keyMapper).get(), Opt.ofNullable(element).map(valueMapper).get()); return new SimpleCollector<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID); } @@ -241,15 +233,67 @@ public class CollectorUtil { */ 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; - } + 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; + } ); } + /** + * 将流转为{@link EasyStream} + * + * @param 输入元素类型 + * @return 收集器 + */ + public static Collector> toEasyStream() { + return transform(ArrayList::new, EasyStream::of); + } + + /** + * 收集元素,将其转为指定{@link Collection}集合后,再对该集合进行转换,并最终返回转换后的结果。 + * 返回的收集器的效果等同于: + *
{@code
+	 * 	Collection coll = Stream.of(a, b, c, d)
+	 * 		.collect(Collectors.toCollection(collFactory));
+	 * 	R result = mapper.apply(coll);
+	 * }
+ * + * @param collFactory 中间收集输入元素的集合的创建方法 + * @param mapper 最终将元素集合映射为返回值的方法 + * @param 返回值类型 + * @param 输入元素类型 + * @param 中间收集输入元素的集合类型 + * @return 收集器 + */ + public static > Collector transform( + Supplier collFactory, Function mapper) { + Objects.requireNonNull(collFactory); + Objects.requireNonNull(mapper); + return new SimpleCollector<>( + collFactory, C::add, (l1, l2) -> { l1.addAll(l2); return l1; }, mapper, CH_NOID + ); + } + + /** + * 收集元素,将其转为{@link ArrayList}集合后,再对该集合进行转换,并最终返回转换后的结果。 + * 返回的收集器的效果等同于: + *
{@code
+	 * 	List coll = Stream.of(a, b, c, d)
+	 * 		.collect(Collectors.toList());
+	 * 	R result = mapper.apply(coll);
+	 * }
+ * + * @param mapper 最终将元素集合映射为返回值的方法 + * @param 返回值类型 + * @param 输入元素类型 + * @return 收集器 + */ + public static Collector, R> transform(Function, R> mapper) { + return transform(ArrayList::new, mapper); + } } 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 index 570478082..068357369 100644 --- a/hutool-core/src/test/java/cn/hutool/core/stream/CollectorUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/stream/CollectorUtilTest.java @@ -4,11 +4,9 @@ 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.*; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * CollectorUtilTest @@ -21,17 +19,36 @@ public class CollectorUtilTest { @Test public void reduceListMapTest() { final Set> nameScoreMapList = StreamUtil.of( - // 集合内的第一个map,包含两个key value - MapUtil.builder("苏格拉底", 1).put("特拉叙马霍斯", 3).build(), - MapUtil.of("苏格拉底", 2), - MapUtil.of("特拉叙马霍斯", 1), - MapUtil.of("特拉叙马霍斯", 2) + // 集合内的第一个map,包含两个key value + MapUtil.builder("苏格拉底", 1).put("特拉叙马霍斯", 3).build(), + MapUtil.of("苏格拉底", 2), + MapUtil.of("特拉叙马霍斯", 1), + MapUtil.of("特拉叙马霍斯", 2) ).collect(Collectors.toSet()); // 执行聚合 final Map> nameScoresMap = nameScoreMapList.stream().collect(CollectorUtil.reduceListMap()); Assert.assertEquals(MapUtil.builder("苏格拉底", Arrays.asList(1, 2)) - .put("特拉叙马霍斯", Arrays.asList(3, 1, 2)).build(), - nameScoresMap); + .put("特拉叙马霍斯", Arrays.asList(3, 1, 2)).build(), + nameScoresMap); } + + @Test + public void testTransform() { + Stream stream = Stream.of(1, 2, 3, 4) + .collect(CollectorUtil.transform(EasyStream::of)); + Assert.assertEquals(EasyStream.class, stream.getClass()); + + stream = Stream.of(1, 2, 3, 4) + .collect(CollectorUtil.transform(HashSet::new, EasyStream::of)); + Assert.assertEquals(EasyStream.class, stream.getClass()); + } + + @Test + public void testToEasyStream() { + Stream stream =Stream.of(1, 2, 3, 4) + .collect(CollectorUtil.toEasyStream()); + Assert.assertEquals(EasyStream.class, stream.getClass()); + } + }