mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
修复CollectorUtil.reduceListMap与collectors.groupby一起使用时出现与预期不符问题
This commit is contained in:
parent
da1e857c07
commit
7a4cac2963
@ -35,7 +35,7 @@ public class CollectorUtil {
|
|||||||
* 说明已包含IDENTITY_FINISH特征 为 Characteristics.IDENTITY_FINISH 的缩写
|
* 说明已包含IDENTITY_FINISH特征 为 Characteristics.IDENTITY_FINISH 的缩写
|
||||||
*/
|
*/
|
||||||
public static final Set<Collector.Characteristics> CH_ID
|
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特征
|
* 说明不包含IDENTITY_FINISH特征
|
||||||
*/
|
*/
|
||||||
@ -80,11 +80,11 @@ public class CollectorUtil {
|
|||||||
final CharSequence suffix,
|
final CharSequence suffix,
|
||||||
final Function<T, ? extends CharSequence> toStringFunc) {
|
final Function<T, ? extends CharSequence> toStringFunc) {
|
||||||
return new SimpleCollector<>(
|
return new SimpleCollector<>(
|
||||||
() -> new StringJoiner(delimiter, prefix, suffix),
|
() -> new StringJoiner(delimiter, prefix, suffix),
|
||||||
(joiner, ele) -> joiner.add(toStringFunc.apply(ele)),
|
(joiner, ele) -> joiner.add(toStringFunc.apply(ele)),
|
||||||
StringJoiner::merge,
|
StringJoiner::merge,
|
||||||
StringJoiner::toString,
|
StringJoiner::toString,
|
||||||
Collections.emptySet()
|
Collections.emptySet()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,11 +208,11 @@ public class CollectorUtil {
|
|||||||
* 提供对null值友好的groupingBy操作的{@link Collector}实现,
|
* 提供对null值友好的groupingBy操作的{@link Collector}实现,
|
||||||
* 对集合分组,然后对分组后的值集合进行映射
|
* 对集合分组,然后对分组后的值集合进行映射
|
||||||
*
|
*
|
||||||
* @param classifier 分组依据
|
* @param classifier 分组依据
|
||||||
* @param valueMapper 值映射方法
|
* @param valueMapper 值映射方法
|
||||||
* @param <T> 元素类型
|
* @param <T> 元素类型
|
||||||
* @param <K> 键类型
|
* @param <K> 键类型
|
||||||
* @param <R> 值类型
|
* @param <R> 值类型
|
||||||
* @return {@link Collector}
|
* @return {@link Collector}
|
||||||
*/
|
*/
|
||||||
public static <T, K, R> Collector<T, ?, Map<K, List<R>>> groupingBy(
|
public static <T, K, R> Collector<T, ?, Map<K, List<R>>> groupingBy(
|
||||||
@ -284,7 +284,7 @@ public class CollectorUtil {
|
|||||||
final BinaryOperator<U> mergeFunction,
|
final BinaryOperator<U> mergeFunction,
|
||||||
final Supplier<M> mapSupplier) {
|
final Supplier<M> mapSupplier) {
|
||||||
final BiConsumer<M, T> accumulator
|
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);
|
return new SimpleCollector<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,13 +330,18 @@ public class CollectorUtil {
|
|||||||
*/
|
*/
|
||||||
public static <K, V, R extends Map<K, List<V>>> Collector<Map<K, V>, ?, R> reduceListMap(final Supplier<R> mapSupplier) {
|
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 -> {
|
return Collectors.reducing(mapSupplier.get(), value -> {
|
||||||
final R result = mapSupplier.get();
|
final R result = mapSupplier.get();
|
||||||
value.forEach((k, v) -> result.computeIfAbsent(k, i -> new ArrayList<>()).add(v));
|
value.forEach((k, v) -> result.computeIfAbsent(k, i -> new ArrayList<>()).add(v));
|
||||||
return result;
|
return result;
|
||||||
}, (l, r) -> {
|
}, (l, r) -> {
|
||||||
r.forEach((k, v) -> l.computeIfAbsent(k, i -> new ArrayList<>()).addAll(v));
|
final R resultMap = mapSupplier.get();
|
||||||
return l;
|
resultMap.putAll(l);
|
||||||
}
|
r.forEach((k, v) -> {
|
||||||
|
final List<V> list = resultMap.computeIfAbsent(k, i -> new ArrayList<>());
|
||||||
|
list.addAll(v);
|
||||||
|
});
|
||||||
|
return resultMap;
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,7 +355,7 @@ public class CollectorUtil {
|
|||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public static <T, K> Collector<T, List<T>, EntryStream<K, T>> toEntryStream(
|
public static <T, K> Collector<T, List<T>, EntryStream<K, T>> toEntryStream(
|
||||||
final Function<? super T, ? extends K> keyMapper) {
|
final Function<? super T, ? extends K> keyMapper) {
|
||||||
return toEntryStream(keyMapper, Function.identity());
|
return toEntryStream(keyMapper, Function.identity());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,7 +371,7 @@ public class CollectorUtil {
|
|||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public static <T, K, V> Collector<T, List<T>, EntryStream<K, V>> toEntryStream(
|
public static <T, K, V> Collector<T, List<T>, EntryStream<K, V>> toEntryStream(
|
||||||
final Function<? super T, ? extends K> keyMapper, final Function<? super T, ? extends V> valueMapper) {
|
final Function<? super T, ? extends K> keyMapper, final Function<? super T, ? extends V> valueMapper) {
|
||||||
Objects.requireNonNull(keyMapper);
|
Objects.requireNonNull(keyMapper);
|
||||||
Objects.requireNonNull(valueMapper);
|
Objects.requireNonNull(valueMapper);
|
||||||
return transform(ArrayList::new, list -> EntryStream.of(list, keyMapper, valueMapper));
|
return transform(ArrayList::new, list -> EntryStream.of(list, keyMapper, valueMapper));
|
||||||
@ -401,11 +406,11 @@ public class CollectorUtil {
|
|||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public static <T, R, C extends Collection<T>> Collector<T, C, R> transform(
|
public static <T, R, C extends Collection<T>> Collector<T, C, R> transform(
|
||||||
final Supplier<C> collFactory, final Function<C, R> mapper) {
|
final Supplier<C> collFactory, final Function<C, R> mapper) {
|
||||||
Objects.requireNonNull(collFactory);
|
Objects.requireNonNull(collFactory);
|
||||||
Objects.requireNonNull(mapper);
|
Objects.requireNonNull(mapper);
|
||||||
return new SimpleCollector<>(
|
return new SimpleCollector<>(
|
||||||
collFactory, C::add, (l1, l2) -> {
|
collFactory, C::add, (l1, l2) -> {
|
||||||
l1.addAll(l2);
|
l1.addAll(l2);
|
||||||
return l1;
|
return l1;
|
||||||
}, mapper, CH_NOID
|
}, mapper, CH_NOID
|
||||||
@ -458,8 +463,8 @@ public class CollectorUtil {
|
|||||||
final Collector<? super T, A, R> downstream) {
|
final Collector<? super T, A, R> downstream) {
|
||||||
final BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
|
final BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
|
||||||
return new SimpleCollector<>(downstream.supplier(),
|
return new SimpleCollector<>(downstream.supplier(),
|
||||||
(r, t) -> Opt.of(t).filter(predicate).ifPresent(e -> downstreamAccumulator.accept(r, e)),
|
(r, t) -> Opt.of(t).filter(predicate).ifPresent(e -> downstreamAccumulator.accept(r, e)),
|
||||||
downstream.combiner(), downstream.finisher(),
|
downstream.combiner(), downstream.finisher(),
|
||||||
downstream.characteristics());
|
downstream.characteristics());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.core.stream;
|
package org.dromara.hutool.core.stream;
|
||||||
|
|
||||||
|
import org.dromara.hutool.core.collection.ListUtil;
|
||||||
import org.dromara.hutool.core.map.MapUtil;
|
import org.dromara.hutool.core.map.MapUtil;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@ -44,6 +45,22 @@ public class CollectorUtilTest {
|
|||||||
Assertions.assertEquals(MapUtil.builder("苏格拉底", Arrays.asList(1, 2))
|
Assertions.assertEquals(MapUtil.builder("苏格拉底", Arrays.asList(1, 2))
|
||||||
.put("特拉叙马霍斯", Arrays.asList(3, 1, 2)).build(),
|
.put("特拉叙马霍斯", Arrays.asList(3, 1, 2)).build(),
|
||||||
nameScoresMap);
|
nameScoresMap);
|
||||||
|
|
||||||
|
final List<Map<String, String>> data = ListUtil.of(
|
||||||
|
MapUtil.builder("name", "sam").put("count", "80").map(),
|
||||||
|
MapUtil.builder("name", "sam").put("count", "81").map(),
|
||||||
|
MapUtil.builder("name", "sam").put("count", "82").map(),
|
||||||
|
MapUtil.builder("name", "jack").put("count", "80").map(),
|
||||||
|
MapUtil.builder("name", "jack").put("count", "90").map()
|
||||||
|
);
|
||||||
|
|
||||||
|
final Map<String, Map<String, List<String>>> nameMap = data.stream()
|
||||||
|
.collect(Collectors.groupingBy(e -> e.get("name"), CollectorUtil.reduceListMap()));
|
||||||
|
Assertions.assertEquals(MapUtil.builder("jack", MapUtil.builder("name", Arrays.asList("jack", "jack"))
|
||||||
|
.put("count", Arrays.asList("80", "90")).build())
|
||||||
|
.put("sam", MapUtil.builder("name", Arrays.asList("sam", "sam", "sam"))
|
||||||
|
.put("count", Arrays.asList("80", "81", "82")).build())
|
||||||
|
.build(), nameMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -93,7 +110,7 @@ public class CollectorUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGroupingByAfterValueMapped() {
|
public void testGroupingByAfterValueMapped() {
|
||||||
List<Integer> list = Arrays.asList(1, 1, 2, 2, 3, 4);
|
final List<Integer> list = Arrays.asList(1, 1, 2, 2, 3, 4);
|
||||||
Map<Boolean, Set<String>> map = list.stream()
|
Map<Boolean, Set<String>> map = list.stream()
|
||||||
.collect(CollectorUtil.groupingBy(t -> (t & 1) == 0, String::valueOf, LinkedHashSet::new, LinkedHashMap::new));
|
.collect(CollectorUtil.groupingBy(t -> (t & 1) == 0, String::valueOf, LinkedHashSet::new, LinkedHashMap::new));
|
||||||
|
|
||||||
@ -107,7 +124,7 @@ public class CollectorUtilTest {
|
|||||||
Assertions.assertEquals(new LinkedHashSet<>(Arrays.asList("2", "4")), map.get(Boolean.TRUE));
|
Assertions.assertEquals(new LinkedHashSet<>(Arrays.asList("2", "4")), map.get(Boolean.TRUE));
|
||||||
Assertions.assertEquals(new LinkedHashSet<>(Arrays.asList("1", "3")), map.get(Boolean.FALSE));
|
Assertions.assertEquals(new LinkedHashSet<>(Arrays.asList("1", "3")), map.get(Boolean.FALSE));
|
||||||
|
|
||||||
Map<Boolean, List<String>> map2 = list.stream()
|
final Map<Boolean, List<String>> map2 = list.stream()
|
||||||
.collect(CollectorUtil.groupingBy(t -> (t & 1) == 0, String::valueOf));
|
.collect(CollectorUtil.groupingBy(t -> (t & 1) == 0, String::valueOf));
|
||||||
Assertions.assertEquals(Arrays.asList("2", "2", "4"), map2.get(Boolean.TRUE));
|
Assertions.assertEquals(Arrays.asList("2", "2", "4"), map2.get(Boolean.TRUE));
|
||||||
Assertions.assertEquals(Arrays.asList("1", "1", "3"), map2.get(Boolean.FALSE));
|
Assertions.assertEquals(Arrays.asList("1", "1", "3"), map2.get(Boolean.FALSE));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user