mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
添加支持对流进行转换的收集器
This commit is contained in:
parent
9e20dbb7a0
commit
4893a5e9aa
@ -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<Collector.Characteristics> 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 <T> Collector<T, ?, String> joining(final CharSequence delimiter,
|
||||
final Function<T, ? extends CharSequence> toStringFunc) {
|
||||
final Function<T, ? extends CharSequence> toStringFunc) {
|
||||
return joining(delimiter, StrUtil.EMPTY, StrUtil.EMPTY, toStringFunc);
|
||||
}
|
||||
|
||||
@ -73,15 +65,15 @@ public class CollectorUtil {
|
||||
* @return {@link Collector}
|
||||
*/
|
||||
public static <T> Collector<T, ?, String> joining(final CharSequence delimiter,
|
||||
final CharSequence prefix,
|
||||
final CharSequence suffix,
|
||||
final Function<T, ? extends CharSequence> toStringFunc) {
|
||||
final CharSequence prefix,
|
||||
final CharSequence suffix,
|
||||
final Function<T, ? extends CharSequence> 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 <T, K, D, A, M extends Map<K, D>> Collector<T, ?, M> groupingBy(final Function<? super T, ? extends K> classifier,
|
||||
final Supplier<M> mapFactory,
|
||||
final Collector<? super T, A, D> downstream) {
|
||||
final Supplier<M> mapFactory,
|
||||
final Collector<? super T, A, D> downstream) {
|
||||
final Supplier<A> downstreamSupplier = downstream.supplier();
|
||||
final BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
|
||||
final BiConsumer<Map<K, A>, T> accumulator = (m, t) -> {
|
||||
@ -141,7 +133,7 @@ public class CollectorUtil {
|
||||
*/
|
||||
public static <T, K, A, D>
|
||||
Collector<T, ?, Map<K, D>> groupingBy(final Function<? super T, ? extends K> classifier,
|
||||
final Collector<? super T, A, D> downstream) {
|
||||
final Collector<? super T, A, D> downstream) {
|
||||
return groupingBy(classifier, HashMap::new, downstream);
|
||||
}
|
||||
|
||||
@ -171,8 +163,8 @@ public class CollectorUtil {
|
||||
*/
|
||||
public static <T, K, U>
|
||||
Collector<T, ?, Map<K, U>> toMap(final Function<? super T, ? extends K> keyMapper,
|
||||
final Function<? super T, ? extends U> valueMapper,
|
||||
final BinaryOperator<U> mergeFunction) {
|
||||
final Function<? super T, ? extends U> valueMapper,
|
||||
final BinaryOperator<U> mergeFunction) {
|
||||
return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
|
||||
}
|
||||
|
||||
@ -191,11 +183,11 @@ public class CollectorUtil {
|
||||
*/
|
||||
public static <T, K, U, M extends Map<K, U>>
|
||||
Collector<T, ?, M> toMap(final Function<? super T, ? extends K> keyMapper,
|
||||
final Function<? super T, ? extends U> valueMapper,
|
||||
final BinaryOperator<U> mergeFunction,
|
||||
final Supplier<M> mapSupplier) {
|
||||
final Function<? super T, ? extends U> valueMapper,
|
||||
final BinaryOperator<U> mergeFunction,
|
||||
final Supplier<M> mapSupplier) {
|
||||
final BiConsumer<M, T> 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 <K, V, R extends Map<K, List<V>>> Collector<Map<K, V>, ?, R> reduceListMap(final Supplier<R> 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 <T> 输入元素类型
|
||||
* @return 收集器
|
||||
*/
|
||||
public static <T> Collector<T, ?, EasyStream<T>> toEasyStream() {
|
||||
return transform(ArrayList::new, EasyStream::of);
|
||||
}
|
||||
|
||||
/**
|
||||
* 收集元素,将其转为指定{@link Collection}集合后,再对该集合进行转换,并最终返回转换后的结果。
|
||||
* 返回的收集器的效果等同于:
|
||||
* <pre>{@code
|
||||
* Collection<T> coll = Stream.of(a, b, c, d)
|
||||
* .collect(Collectors.toCollection(collFactory));
|
||||
* R result = mapper.apply(coll);
|
||||
* }</pre>
|
||||
*
|
||||
* @param collFactory 中间收集输入元素的集合的创建方法
|
||||
* @param mapper 最终将元素集合映射为返回值的方法
|
||||
* @param <R> 返回值类型
|
||||
* @param <T> 输入元素类型
|
||||
* @param <C> 中间收集输入元素的集合类型
|
||||
* @return 收集器
|
||||
*/
|
||||
public static <T, R, C extends Collection<T>> Collector<T, C, R> transform(
|
||||
Supplier<C> collFactory, Function<C, R> 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}集合后,再对该集合进行转换,并最终返回转换后的结果。
|
||||
* 返回的收集器的效果等同于:
|
||||
* <pre>{@code
|
||||
* List<T> coll = Stream.of(a, b, c, d)
|
||||
* .collect(Collectors.toList());
|
||||
* R result = mapper.apply(coll);
|
||||
* }</pre>
|
||||
*
|
||||
* @param mapper 最终将元素集合映射为返回值的方法
|
||||
* @param <R> 返回值类型
|
||||
* @param <T> 输入元素类型
|
||||
* @return 收集器
|
||||
*/
|
||||
public static <T, R> Collector<T, List<T>, R> transform(Function<List<T>, R> mapper) {
|
||||
return transform(ArrayList::new, mapper);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<Map<String, Integer>> 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<String, List<Integer>> 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<Integer> 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<Integer> stream =Stream.of(1, 2, 3, 4)
|
||||
.collect(CollectorUtil.toEasyStream());
|
||||
Assert.assertEquals(EasyStream.class, stream.getClass());
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user