mirror of
https://gitee.com/dromara/hutool.git
synced 2025-05-03 12:18:01 +08:00
Merge pull request #3692 from huangxin8899/v5-dev
增加函数式构建树的方法(无需继承特定Tree类)
This commit is contained in:
commit
af67650742
@ -5,9 +5,10 @@ import cn.hutool.core.lang.tree.parser.DefaultNodeParser;
|
|||||||
import cn.hutool.core.lang.tree.parser.NodeParser;
|
import cn.hutool.core.lang.tree.parser.NodeParser;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.Map;
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 树工具类
|
* 树工具类
|
||||||
@ -277,4 +278,52 @@ public class TreeUtil {
|
|||||||
public static <E> Tree<E> createEmptyNode(E id) {
|
public static <E> Tree<E> createEmptyNode(E id) {
|
||||||
return new Tree<E>().setId(id);
|
return new Tree<E>().setId(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 函数式构建树状结构(无需继承Tree类)
|
||||||
|
*
|
||||||
|
* @param nodes 需要构建树集合
|
||||||
|
* @param rootId 根节点ID
|
||||||
|
* @param idFunc 获取节点ID函数
|
||||||
|
* @param parentIdFunc 获取节点父ID函数
|
||||||
|
* @param setChildFunc 设置孩子集合函数
|
||||||
|
* @param <T> 节点ID类型
|
||||||
|
* @param <E> 节点类型
|
||||||
|
* @return List
|
||||||
|
*/
|
||||||
|
public static <T, E> List<E> build(List<E> nodes, T rootId, Function<E, T> idFunc, Function<E, T> parentIdFunc, BiConsumer<E, List<E>> setChildFunc) {
|
||||||
|
List<E> rootList = nodes.stream().filter(tree -> parentIdFunc.apply(tree).equals(rootId)).collect(Collectors.toList());
|
||||||
|
Map<T, T> filterOperated = new HashMap<>(rootList.size() + nodes.size());
|
||||||
|
//对每个根节点都封装它的孩子节点
|
||||||
|
rootList.forEach(root -> setChildren(root, nodes, filterOperated, idFunc, parentIdFunc, setChildFunc));
|
||||||
|
return rootList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 封装孩子节点
|
||||||
|
*
|
||||||
|
* @param root 根节点
|
||||||
|
* @param nodes 节点集合
|
||||||
|
* @param filterOperated 过滤操作Map
|
||||||
|
* @param idFunc 获取节点ID函数
|
||||||
|
* @param parentIdFunc 获取节点父ID函数
|
||||||
|
* @param setChildFunc 设置孩子集合函数
|
||||||
|
* @param <T> 节点ID类型
|
||||||
|
* @param <E> 节点类型
|
||||||
|
*/
|
||||||
|
private static <T, E> void setChildren(E root, List<E> nodes, Map<T, T> filterOperated, Function<E, T> idFunc, Function<E, T> parentIdFunc, BiConsumer<E, List<E>> setChildFunc) {
|
||||||
|
List<E> children = new ArrayList<>();
|
||||||
|
nodes.stream()
|
||||||
|
//过滤出未操作过的节点
|
||||||
|
.filter(body -> !filterOperated.containsKey(idFunc.apply(body)))
|
||||||
|
//过滤出孩子节点
|
||||||
|
.filter(body -> Objects.equals(idFunc.apply(root), parentIdFunc.apply(body)))
|
||||||
|
.forEach(body -> {
|
||||||
|
filterOperated.put(idFunc.apply(body), idFunc.apply(root));
|
||||||
|
children.add(body);
|
||||||
|
//递归 对每个孩子节点执行同样操作
|
||||||
|
setChildren(body, nodes, filterOperated, idFunc, parentIdFunc, setChildFunc);
|
||||||
|
});
|
||||||
|
setChildFunc.accept(root, children);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package cn.hutool.core.lang.tree;
|
package cn.hutool.core.lang.tree;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import lombok.Data;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -122,4 +123,39 @@ public class TreeTest {
|
|||||||
tree.walk((tr) -> ids2.add(tr.getId()));
|
tree.walk((tr) -> ids2.add(tr.getId()));
|
||||||
assertEquals(7, ids2.size());
|
assertEquals(7, ids2.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
static class Area {
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
private Integer parentId;
|
||||||
|
private List<Area> childrenList;
|
||||||
|
|
||||||
|
public Area(Integer id, String name, Integer parentId) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.parentId = parentId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 模拟数据
|
||||||
|
static List<Area> areaList = CollUtil.newArrayList();
|
||||||
|
static {
|
||||||
|
areaList.add(new Area(1, "中国", 0));
|
||||||
|
areaList.add(new Area(2, "北京", 1));
|
||||||
|
areaList.add(new Area(3, "上海", 1));
|
||||||
|
areaList.add(new Area(4, "广东", 1));
|
||||||
|
areaList.add(new Area(5, "广州", 4));
|
||||||
|
areaList.add(new Area(6, "深圳", 4));
|
||||||
|
areaList.add(new Area(7, "浙江", 1));
|
||||||
|
areaList.add(new Area(8, "杭州", 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void builderTest() {
|
||||||
|
List<Area> list = TreeUtil.build(areaList, 0, Area::getId, Area::getParentId, Area::setChildrenList);
|
||||||
|
final Area root = list.get(0);
|
||||||
|
final Integer parentId = root.getChildrenList().get(0).getParentId();
|
||||||
|
assertEquals(root.getId(), parentId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user