:trollface: 优化EasyStream中toTree对predicate的处理,过滤掉id为null的元素,避免StackOverflow

This commit is contained in:
VampireAchao 2022-10-07 11:53:31 +08:00
parent 2c2ad12972
commit c1acb2e148
3 changed files with 14 additions and 21 deletions

View File

@ -373,7 +373,7 @@ public class CollectorUtil {
* <p>将集合转换为树默认用 {@code parentId == null} 来判断树的根节点 * <p>将集合转换为树默认用 {@code parentId == null} 来判断树的根节点
* 因为需要在当前传入数据里查找所以这是一个结束操作 <br> * 因为需要在当前传入数据里查找所以这是一个结束操作 <br>
* *
* @param idGetter id的getter对应的lambda可以写作 {@code Student::getId} * @param idGetter id的getter对应的lambda可以写作 {@code Student::getId} 会过滤掉id为null的元素
* @param pIdGetter parentId的getter对应的lambda可以写作 {@code Student::getParentId} * @param pIdGetter parentId的getter对应的lambda可以写作 {@code Student::getParentId}
* @param childrenSetter children的setter对应的lambda可以写作{ @code Student::setChildren} * @param childrenSetter children的setter对应的lambda可以写作{ @code Student::setChildren}
* @param isParallel 是否并行去组装数据量特别大时使用 * @param isParallel 是否并行去组装数据量特别大时使用
@ -397,7 +397,7 @@ public class CollectorUtil {
* <p>将集合转换为树默认用 {@code parentId == pidValue} 来判断树的根节点可以为null * <p>将集合转换为树默认用 {@code parentId == pidValue} 来判断树的根节点可以为null
* 因为需要在当前传入数据里查找所以这是一个结束操作 <br> * 因为需要在当前传入数据里查找所以这是一个结束操作 <br>
* *
* @param idGetter id的getter对应的lambda可以写作 {@code Student::getId} * @param idGetter id的getter对应的lambda可以写作 {@code Student::getId} 会过滤掉id为null的元素
* @param pIdGetter parentId的getter对应的lambda可以写作 {@code Student::getParentId} * @param pIdGetter parentId的getter对应的lambda可以写作 {@code Student::getParentId}
* @param pidValue pid的值 * @param pidValue pid的值
* @param childrenSetter children的setter对应的lambda可以写作{ @code Student::setChildren} * @param childrenSetter children的setter对应的lambda可以写作{ @code Student::setChildren}
@ -417,7 +417,7 @@ public class CollectorUtil {
final R pidValue, final R pidValue,
final BiConsumer<T, List<T>> childrenSetter, final BiConsumer<T, List<T>> childrenSetter,
final boolean isParallel) { final boolean isParallel) {
return Collectors.collectingAndThen(groupingBy(pIdGetter, Collectors.toList()), return Collectors.collectingAndThen(filtering(e -> idGetter.apply(e) != null, groupingBy(pIdGetter, Collectors.toList())),
getChildrenFromMapByPidAndSet(idGetter, pIdValuesMap -> pIdValuesMap.get(pidValue), childrenSetter, isParallel)); getChildrenFromMapByPidAndSet(idGetter, pIdValuesMap -> pIdValuesMap.get(pidValue), childrenSetter, isParallel));
} }
@ -425,7 +425,7 @@ public class CollectorUtil {
* 将集合转换为树自定义根节点的判断条件 * 将集合转换为树自定义根节点的判断条件
* 因为需要在当前传入数据里查找所以这是一个结束操作 * 因为需要在当前传入数据里查找所以这是一个结束操作
* *
* @param idGetter id的getter对应的lambda可以写作 {@code Student::getId} * @param idGetter id的getter对应的lambda可以写作 {@code Student::getId} 会过滤掉id为null的元素
* @param pIdGetter parentId的getter对应的lambda可以写作 {@code Student::getParentId} * @param pIdGetter parentId的getter对应的lambda可以写作 {@code Student::getParentId}
* @param childrenSetter children的setter对应的lambda可以写作 {@code Student::setChildren} * @param childrenSetter children的setter对应的lambda可以写作 {@code Student::setChildren}
* @param parentPredicate 树顶部的判断条件可以写作 {@code s -> Objects.equals(s.getParentId(),0L) } * @param parentPredicate 树顶部的判断条件可以写作 {@code s -> Objects.equals(s.getParentId(),0L) }
@ -447,21 +447,12 @@ public class CollectorUtil {
final Predicate<T> parentPredicate, final Predicate<T> parentPredicate,
final boolean isParallel) { final boolean isParallel) {
final List<T> parents = new ArrayList<>(); final List<T> parents = new ArrayList<>();
return Collectors.collectingAndThen(groupingBy(pIdGetter, return Collectors.collectingAndThen(filtering(e -> {
new SimpleCollector<>(ArrayList::new,
(acc, e) -> {
if (parentPredicate.test(e)) { if (parentPredicate.test(e)) {
parents.add(e); parents.add(e);
} }
if (idGetter.apply(e) != null) { return idGetter.apply(e) != null;
acc.add(e); }, groupingBy(pIdGetter)),
}
},
(left, right) -> {
left.addAll(right);
return left;
},
CH_ID)),
getChildrenFromMapByPidAndSet(idGetter, pIdValuesMap -> parents, childrenSetter, isParallel)); getChildrenFromMapByPidAndSet(idGetter, pIdValuesMap -> parents, childrenSetter, isParallel));
} }

View File

@ -188,7 +188,7 @@ public interface TerminableWrappedStream<T, S extends TerminableWrappedStream<T,
* <p>将集合转换为树默认用 {@code parentId == null} 来判断树的根节点 * <p>将集合转换为树默认用 {@code parentId == null} 来判断树的根节点
* 因为需要在当前传入数据里查找所以这是一个结束操作 <br> * 因为需要在当前传入数据里查找所以这是一个结束操作 <br>
* *
* @param idGetter id的getter对应的lambda可以写作 {@code Student::getId} * @param idGetter id的getter对应的lambda可以写作 {@code Student::getId} 会过滤掉id为null的元素
* @param pIdGetter parentId的getter对应的lambda可以写作 {@code Student::getParentId} * @param pIdGetter parentId的getter对应的lambda可以写作 {@code Student::getParentId}
* @param childrenSetter children的setter对应的lambda可以写作{ @code Student::setChildren} * @param childrenSetter children的setter对应的lambda可以写作{ @code Student::setChildren}
* @param <R> 此处是idparentId的泛型限制 * @param <R> 此处是idparentId的泛型限制
@ -211,7 +211,7 @@ public interface TerminableWrappedStream<T, S extends TerminableWrappedStream<T,
* 将集合转换为树自定义根节点的判断条件 * 将集合转换为树自定义根节点的判断条件
* 因为需要在当前传入数据里查找所以这是一个结束操作 * 因为需要在当前传入数据里查找所以这是一个结束操作
* *
* @param idGetter id的getter对应的lambda可以写作 {@code Student::getId} * @param idGetter id的getter对应的lambda可以写作 {@code Student::getId} 会过滤掉id为null的元素
* @param pIdGetter parentId的getter对应的lambda可以写作 {@code Student::getParentId} * @param pIdGetter parentId的getter对应的lambda可以写作 {@code Student::getParentId}
* @param childrenSetter children的setter对应的lambda可以写作 {@code Student::setChildren} * @param childrenSetter children的setter对应的lambda可以写作 {@code Student::setChildren}
* @param parentPredicate 树顶部的判断条件可以写作 {@code s -> Objects.equals(s.getParentId(),0L) } * @param parentPredicate 树顶部的判断条件可以写作 {@code s -> Objects.equals(s.getParentId(),0L) }

View File

@ -434,6 +434,8 @@ public class EasyStreamTest {
Consumer<Object> test = o -> { Consumer<Object> test = o -> {
final List<Student> studentTree = EasyStream final List<Student> studentTree = EasyStream
.of( .of(
// 会过滤掉id为null的元素
Student.builder().name("top").build(),
Student.builder().id(1L).name("dromara").build(), Student.builder().id(1L).name("dromara").build(),
Student.builder().id(2L).name("baomidou").build(), Student.builder().id(2L).name("baomidou").build(),
Student.builder().id(3L).name("hutool").parentId(1L).build(), Student.builder().id(3L).name("hutool").parentId(1L).build(),