mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
优化toTree方法的实现,使用循环代替递归;
This commit is contained in:
parent
9417bbee2e
commit
28f6a76933
@ -1,7 +1,7 @@
|
|||||||
package cn.hutool.core.stream;
|
package cn.hutool.core.stream;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.ListUtil;
|
||||||
import cn.hutool.core.lang.Opt;
|
import cn.hutool.core.lang.Opt;
|
||||||
import cn.hutool.core.lang.mutable.MutableObj;
|
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
import cn.hutool.core.util.ObjUtil;
|
import cn.hutool.core.util.ObjUtil;
|
||||||
|
|
||||||
@ -267,7 +267,7 @@ public class EasyStream<T> extends AbstractEnhancedWrappedStream<T, EasyStream<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}
|
||||||
@ -285,12 +285,13 @@ public class EasyStream<T> extends AbstractEnhancedWrappedStream<T, EasyStream<T
|
|||||||
final Function<T, R> idGetter,
|
final Function<T, R> idGetter,
|
||||||
final Function<T, R> pIdGetter,
|
final Function<T, R> pIdGetter,
|
||||||
final BiConsumer<T, List<T>> childrenSetter) {
|
final BiConsumer<T, List<T>> childrenSetter) {
|
||||||
final Map<R, List<T>> pIdValuesMap = group(pIdGetter);
|
// 使用 parentId == null 判断是否为根节点
|
||||||
return getChildrenFromMapByPidAndSet(idGetter, childrenSetter, pIdValuesMap, pIdValuesMap.get(null));
|
final Predicate<T> parentPredicate = node -> null == pIdGetter.apply(node);
|
||||||
|
return toTree(idGetter, pIdGetter, childrenSetter, parentPredicate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将集合转换为树,自定义树顶部的判断条件,内置一个小递归(没错,lambda可以写递归)
|
* 将集合转换为树,自定义根节点的判断条件
|
||||||
* 因为需要在当前传入数据里查找,所以这是一个结束操作
|
* 因为需要在当前传入数据里查找,所以这是一个结束操作
|
||||||
*
|
*
|
||||||
* @param idGetter id的getter对应的lambda,可以写作 {@code Student::getId}
|
* @param idGetter id的getter对应的lambda,可以写作 {@code Student::getId}
|
||||||
@ -305,46 +306,31 @@ public class EasyStream<T> extends AbstractEnhancedWrappedStream<T, EasyStream<T
|
|||||||
* .toTree(Student::getId, Student::getParentId, Student::setChildren, Student::getMatchParent);
|
* .toTree(Student::getId, Student::getParentId, Student::setChildren, Student::getMatchParent);
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public <R extends Comparable<R>> List<T> toTree(
|
public <R extends Comparable<R>> List<T> toTree(
|
||||||
final Function<T, R> idGetter,
|
final Function<T, R> idGetter,
|
||||||
final Function<T, R> pIdGetter,
|
final Function<T, R> pIdGetter,
|
||||||
final BiConsumer<T, List<T>> childrenSetter,
|
final BiConsumer<T, List<T>> childrenSetter,
|
||||||
final Predicate<T> parentPredicate) {
|
final Predicate<T> parentPredicate) {
|
||||||
Objects.requireNonNull(parentPredicate);
|
|
||||||
final List<T> list = toList();
|
|
||||||
// 根节点列表
|
|
||||||
final List<T> parents = EasyStream.of(list).filter(parentPredicate).toList();
|
|
||||||
return getChildrenFromMapByPidAndSet(idGetter, childrenSetter, EasyStream.of(list).group(pIdGetter), parents);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* toTree的内联函数,内置一个小递归(没错,lambda可以写递归)
|
|
||||||
* 因为需要在当前传入数据里查找,所以这是一个结束操作
|
|
||||||
*
|
|
||||||
* @param idGetter id的getter对应的lambda,可以写作 {@code Student::getId}
|
|
||||||
* @param childrenSetter children的setter对应的lambda,可以写作 {@code Student::setChildren}
|
|
||||||
* @param pIdValuesMap parentId和值组成的map,用来降低复杂度
|
|
||||||
* @param parents 顶部数据
|
|
||||||
* @param <R> 此处是id的泛型限制
|
|
||||||
* @return list 组装好的树
|
|
||||||
*/
|
|
||||||
private <R extends Comparable<R>> List<T> getChildrenFromMapByPidAndSet(
|
|
||||||
final Function<T, R> idGetter,
|
|
||||||
final BiConsumer<T, List<T>> childrenSetter,
|
|
||||||
final Map<R, List<T>> pIdValuesMap,
|
|
||||||
final List<T> parents) {
|
|
||||||
Objects.requireNonNull(idGetter);
|
Objects.requireNonNull(idGetter);
|
||||||
|
Objects.requireNonNull(pIdGetter);
|
||||||
Objects.requireNonNull(childrenSetter);
|
Objects.requireNonNull(childrenSetter);
|
||||||
Objects.requireNonNull(pIdValuesMap);
|
Objects.requireNonNull(parentPredicate);
|
||||||
final MutableObj<Consumer<List<T>>> recursiveRef = new MutableObj<>();
|
|
||||||
final Consumer<List<T>> recursive = values -> EasyStream.of(values, isParallel()).forEach(value -> {
|
List<T> nodeList = toList();
|
||||||
final List<T> children = pIdValuesMap.get(idGetter.apply(value));
|
// 父id 关联的 子节点列表
|
||||||
childrenSetter.accept(value, children);
|
final Map<R, List<T>> pId2ChildrenMap = of(nodeList).group(pIdGetter);
|
||||||
recursiveRef.get().accept(children);
|
List<T> parents = ListUtil.of();
|
||||||
});
|
|
||||||
recursiveRef.set(recursive);
|
for (T node : nodeList) {
|
||||||
recursive.accept(parents);
|
if (parentPredicate.test(node)) {
|
||||||
|
parents.add(node);
|
||||||
|
}
|
||||||
|
// 设置 该节点的子节点列表
|
||||||
|
final List<T> children = pId2ChildrenMap.get(idGetter.apply(node));
|
||||||
|
if (children != null) {
|
||||||
|
childrenSetter.accept(node, children);
|
||||||
|
}
|
||||||
|
}
|
||||||
return parents;
|
return parents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user