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 71bdc4ff6..20732ff6d 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 @@ -430,124 +430,6 @@ public class CollectorUtil { return toMap(Map.Entry::getKey, Map.Entry::getValue); } - /** - *

将集合转换为树,默认用 {@code parentId == null} 来判断树的根节点 - * 因为需要在当前传入数据里查找,所以这是一个结束操作
- * - * @param idGetter id的getter对应的lambda,可以写作 {@code Student::getId} 会过滤掉id为null的元素 - * @param pIdGetter parentId的getter对应的lambda,可以写作 {@code Student::getParentId} - * @param childrenSetter children的setter对应的lambda,可以写作{ @code Student::setChildren} - * @param isParallel 是否并行去组装,数据量特别大时使用 - * @param 此处是元素类型 - * @param 此处是id、parentId的泛型限制 - * @return list 组装好的树
- * eg: - *

{@code
-	 * List studentTree = students.stream().collect(toTree(Student::getId, Student::getParentId, Student::setChildren, isParallel));
-	 * }
- */ - public static , T> Collector> toTree( - final Function idGetter, - final Function pIdGetter, - final BiConsumer> childrenSetter, - final boolean isParallel) { - return toTree(idGetter, pIdGetter, null, childrenSetter, isParallel); - } - - /** - *

将集合转换为树,默认用 {@code parentId == pidValue} 来判断树的根节点,可以为null - * 因为需要在当前传入数据里查找,所以这是一个结束操作
- * - * @param idGetter id的getter对应的lambda,可以写作 {@code Student::getId} 会过滤掉id为null的元素 - * @param pIdGetter parentId的getter对应的lambda,可以写作 {@code Student::getParentId} - * @param pidValue pid的值 - * @param childrenSetter children的setter对应的lambda,可以写作{ @code Student::setChildren} - * @param isParallel 是否并行去组装,数据量特别大时使用 - * @param 此处是元素类型 - * @param 此处是id、parentId的泛型限制 - * @return list 组装好的树
- * eg: - *

{@code
-	 * List studentTree = students.stream().collect(toTree(Student::getId, Student::getParentId, 0L, Student::setChildren, isParallel));
-	 * }
- * @author VampireAchao - */ - public static , T> Collector> toTree( - final Function idGetter, - final Function pIdGetter, - final R pidValue, - final BiConsumer> childrenSetter, - final boolean isParallel) { - return Collectors.collectingAndThen(filtering(e -> idGetter.apply(e) != null, groupingBy(pIdGetter, Collectors.toList())), - getChildrenFromMapByPidAndSet(idGetter, pIdValuesMap -> pIdValuesMap.get(pidValue), childrenSetter, isParallel)); - } - - /** - * 将集合转换为树,自定义根节点的判断条件 - * 因为需要在当前传入数据里查找,所以这是一个结束操作 - * - * @param idGetter id的getter对应的lambda,可以写作 {@code Student::getId} 会过滤掉id为null的元素 - * @param pIdGetter parentId的getter对应的lambda,可以写作 {@code Student::getParentId} - * @param childrenSetter children的setter对应的lambda,可以写作 {@code Student::setChildren} - * @param parentPredicate 树顶部的判断条件,可以写作 {@code s -> Objects.equals(s.getParentId(),0L) } - * @param isParallel 是否并行处理 - * @param 此处是元素类型 - * @param 此处是id、parentId的泛型限制 - * @return list 组装好的树
- * eg: - *
{@code
-	 * List studentTree = EasyStream.of(students).
-	 * 	.toTree(Student::getId, Student::getParentId, Student::setChildren, Student::getMatchParent);
-	 * }
- * @author VampireAchao - */ - public static , T> Collector> toTree( - final Function idGetter, - final Function pIdGetter, - final BiConsumer> childrenSetter, - final Predicate parentPredicate, - final boolean isParallel) { - final List parents = new ArrayList<>(); - return Collectors.collectingAndThen(filtering(e -> { - if (parentPredicate.test(e)) { - parents.add(e); - } - return idGetter.apply(e) != null; - }, groupingBy(pIdGetter)), - getChildrenFromMapByPidAndSet(idGetter, pIdValuesMap -> parents, childrenSetter, isParallel)); - } - - /** - * toTree的内联函数 - * 因为需要在当前传入数据里查找,所以这是一个结束操作 - * - * @param idGetter id的getter对应的lambda,可以写作 {@code Student::getId} - * @param parentFactory 顶部数据工厂方法 - * @param childrenSetter children的setter对应的lambda,可以写作 {@code Student::setChildren} - * @param isParallel 是否并行处理 - * @param 此处是元素类型 - * @param 此处是id的泛型限制 - * @return list 组装好的树 - * @author VampireAchao - */ - private static , T> Function>, List> getChildrenFromMapByPidAndSet( - final Function idGetter, - final Function>, List> parentFactory, - final BiConsumer> childrenSetter, - final boolean isParallel) { - return pIdValuesMap -> { - EasyStream.of(pIdValuesMap.values(), isParallel).flat(Function.identity()) - .forEach(value -> { - final List children = pIdValuesMap.get(idGetter.apply(value)); - if (children != null) { - childrenSetter.accept(value, children); - } - }); - return parentFactory.apply(pIdValuesMap); - }; - } - - /** *

过滤

* diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/TerminableWrappedStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/TerminableWrappedStream.java index 5c61433a0..258518624 100644 --- a/hutool-core/src/main/java/cn/hutool/core/stream/TerminableWrappedStream.java +++ b/hutool-core/src/main/java/cn/hutool/core/stream/TerminableWrappedStream.java @@ -205,83 +205,6 @@ public interface TerminableWrappedStream index.incrementAndGet(), valueMapper, (l, r) -> r); } - - /** - *

将集合转换为树,默认用 {@code parentId == null} 来判断树的根节点 - * 因为需要在当前传入数据里查找,所以这是一个结束操作
- * - * @param idGetter id的getter对应的lambda,可以写作 {@code Student::getId} - * @param pIdGetter parentId的getter对应的lambda,可以写作 {@code Student::getParentId} - * @param childrenSetter children的setter对应的lambda,可以写作{ @code Student::setChildren} - * @param 此处是id、parentId的泛型限制 - * @return list 组装好的树
- * eg: - *

{@code
-	 * List studentTree = EasyStream.of(students).
-	 * 	toTree(Student::getId, Student::getParentId, Student::setChildren);
-	 * }
- * @author VampireAchao - */ - default > List toTree( - final Function idGetter, - final Function pIdGetter, - final BiConsumer> childrenSetter) { - return collect(CollectorUtil.toTree(idGetter, pIdGetter, childrenSetter, isParallel())); - } - - /** - *

将集合转换为树,传入 {@code parentId == pidValue} 来判断树的根节点 - * 因为需要在当前传入数据里查找,所以这是一个结束操作
- * - * @param idGetter id的getter对应的lambda,可以写作 {@code Student::getId} - * @param pIdGetter parentId的getter对应的lambda,可以写作 {@code Student::getParentId} - * @param pIdValue parentId的值,支持 {@code null} - * @param childrenSetter children的setter对应的lambda,可以写作{ @code Student::setChildren} - * @param 此处是id、parentId的泛型限制 - * @return list 组装好的树
- * eg: - *

{@code
-	 * List studentTree = EasyStream.of(students).
-	 * 	toTree(Student::getId, Student::getParentId, 0L, Student::setChildren);
-	 * }
- * @author VampireAchao - */ - default > List toTree( - final Function idGetter, - final Function pIdGetter, - final R pIdValue, - final BiConsumer> childrenSetter) { - return collect(CollectorUtil.toTree(idGetter, pIdGetter, pIdValue, childrenSetter, isParallel())); - } - - /** - * 将集合转换为树,自定义根节点的判断条件 - * 因为需要在当前传入数据里查找,所以这是一个结束操作 - * - * @param idGetter id的getter对应的lambda,可以写作 {@code Student::getId} - * @param pIdGetter parentId的getter对应的lambda,可以写作 {@code Student::getParentId} - * @param childrenSetter children的setter对应的lambda,可以写作 {@code Student::setChildren} - * @param parentPredicate 树顶部的判断条件,可以写作 {@code s -> Objects.equals(s.getParentId(),0L) } - * @param 此处是id、parentId的泛型限制 - * @return list 组装好的树
- * eg: - *
{@code
-	 * List studentTree = EasyStream.of(students).
-	 * 	.toTree(Student::getId, Student::getParentId, Student::setChildren, Student::getMatchParent);
-	 * }
- * @author VampireAchao - */ - default > List toTree( - final Function idGetter, - final Function pIdGetter, - final BiConsumer> childrenSetter, - final Predicate parentPredicate) { - return collect(CollectorUtil.toTree(idGetter, pIdGetter, childrenSetter, parentPredicate, isParallel())); - } - - - // endregion - // region ============ to zip ============ /** diff --git a/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java b/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java index c5128e2f4..39a283f42 100644 --- a/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java @@ -2,19 +2,14 @@ package cn.hutool.core.stream; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.BooleanUtil; -import lombok.Data; -import lombok.experimental.Tolerate; import org.junit.Assert; import org.junit.Test; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.Stream; -import static java.util.Arrays.asList; import static java.util.Collections.singletonList; /** @@ -436,124 +431,4 @@ public class EasyStreamTest { Assert.assertTrue(EasyStream.of(1).isNotEmpty()); } - @Test - public void testToTree() { - Consumer test = o -> { - final List studentTree = EasyStream - .of( - Student.builder().id(1L).name("dromara").build(), - Student.builder().id(2L).name("baomidou").build(), - Student.builder().id(3L).name("hutool").parentId(1L).build(), - Student.builder().id(4L).name("sa-token").parentId(1L).build(), - Student.builder().id(5L).name("mybatis-plus").parentId(2L).build(), - Student.builder().id(6L).name("looly").parentId(3L).build(), - Student.builder().id(7L).name("click33").parentId(4L).build(), - Student.builder().id(8L).name("jobob").parentId(5L).build() - ) - // just 3 lambda,top parentId is null - .toTree(Student::getId, Student::getParentId, Student::setChildren); - Assert.assertEquals(asList( - Student.builder().id(1L).name("dromara") - .children(asList(Student.builder().id(3L).name("hutool").parentId(1L) - .children(singletonList(Student.builder().id(6L).name("looly").parentId(3L).build())) - .build(), - Student.builder().id(4L).name("sa-token").parentId(1L) - .children(singletonList(Student.builder().id(7L).name("click33").parentId(4L).build())) - .build())) - .build(), - Student.builder().id(2L).name("baomidou") - .children(singletonList( - Student.builder().id(5L).name("mybatis-plus").parentId(2L) - .children(singletonList( - Student.builder().id(8L).name("jobob").parentId(5L).build() - )) - .build())) - .build() - ), studentTree); - }; - test = test.andThen(o -> { - final List studentTree = EasyStream - .of( - Student.builder().id(1L).name("dromara").matchParent(true).build(), - Student.builder().id(2L).name("baomidou").matchParent(true).build(), - Student.builder().id(3L).name("hutool").parentId(1L).build(), - Student.builder().id(4L).name("sa-token").parentId(1L).build(), - Student.builder().id(5L).name("mybatis-plus").parentId(2L).build(), - Student.builder().id(6L).name("looly").parentId(3L).build(), - Student.builder().id(7L).name("click33").parentId(4L).build(), - Student.builder().id(8L).name("jobob").parentId(5L).build() - ) - // just 4 lambda ,top by condition - .toTree(Student::getId, Student::getParentId, Student::setChildren, s -> BooleanUtil.isTrue(s.getMatchParent())); - Assert.assertEquals(asList( - Student.builder().id(1L).name("dromara").matchParent(true) - .children(asList(Student.builder().id(3L).name("hutool").parentId(1L) - .children(singletonList(Student.builder().id(6L).name("looly").parentId(3L).build())) - .build(), - Student.builder().id(4L).name("sa-token").parentId(1L) - .children(singletonList(Student.builder().id(7L).name("click33").parentId(4L).build())) - .build())) - .build(), - Student.builder().id(2L).name("baomidou").matchParent(true) - .children(singletonList( - Student.builder().id(5L).name("mybatis-plus").parentId(2L) - .children(singletonList( - Student.builder().id(8L).name("jobob").parentId(5L).build() - )) - .build())) - .build() - ), studentTree); - }); - test.accept(new Object()); - } - - @Test - public void testFlatTree() { - final List studentTree = asList( - Student.builder().id(1L).name("dromara") - .children(asList(Student.builder().id(3L).name("hutool").parentId(1L) - .children(singletonList(Student.builder().id(6L).name("looly").parentId(3L).build())) - .build(), - Student.builder().id(4L).name("sa-token").parentId(1L) - .children(singletonList(Student.builder().id(7L).name("click33").parentId(4L).build())) - .build())) - .build(), - Student.builder().id(2L).name("baomidou") - .children(singletonList( - Student.builder().id(5L).name("mybatis-plus").parentId(2L) - .children(singletonList( - Student.builder().id(8L).name("jobob").parentId(5L).build() - )) - .build())) - .build() - ); - Assert.assertEquals(asList( - Student.builder().id(1L).name("dromara").build(), - Student.builder().id(2L).name("baomidou").build(), - Student.builder().id(3L).name("hutool").parentId(1L).build(), - Student.builder().id(4L).name("sa-token").parentId(1L).build(), - Student.builder().id(5L).name("mybatis-plus").parentId(2L).build(), - Student.builder().id(6L).name("looly").parentId(3L).build(), - Student.builder().id(7L).name("click33").parentId(4L).build(), - Student.builder().id(8L).name("jobob").parentId(5L).build() - ), EasyStream.of(studentTree).flatTree(Student::getChildren, Student::setChildren).sorted(Comparator.comparingLong(Student::getId)).toList()); - - } - - @Data - @lombok.Builder - public static class Student { - private String name; - private Integer age; - private Long id; - private Long parentId; - private List children; - private Boolean matchParent; - - @Tolerate - public Student() { - // this is an accessible parameterless constructor. - } - } - }