目录
问题
一个Java项目中,有多个分类树,每个分类树上节点的属性各不相同,但是构造分类树的逻辑又都是一样的。每个分类树构造都要单独写一个方法的话,会造成代码冗余。
如何解决
使用Java泛型+函数式接口,提取公用逻辑。
代码
构造树工具类
public class TreeUtils {
public final static String ROOT = "root";
/**
* 递归构造树
*
* @param sources 按parentId分类的节点
* @param parentId 父id
* @param getId 获取id
* @param setChildren 设置子节点
* @return 根节点集合
* @param <T> 节点类
* @param <R> id类型
*/
public static <T, R> List<T> buildTree(Map<R, List<T>> sources, R parentId,
Function<T, R> getId, BiConsumer<T, List<T>> setChildren) {
List<T> nodes = sources.getOrDefault(parentId, emptyList());
for (T node : nodes) {
List<T> subNodes = buildTree(sources, getId.apply(node), getId, setChildren);
setChildren.accept(node, subNodes);
}
return nodes;
}
//测试代码
public static void main(String[] args) {
Node root = new Node();
root.setId("1");
root.setPid(null);
root.setName("root");
Node child1 = new Node();
child1.setId("2");
child1.setPid("1");
child1.setName("child1");
Node child2 = new Node();
child2.setId("3");
child2.setPid("1");
child2.setName("child2");
List<Node> children = Arrays.asList(child1, child2);
root.setChildren(children);
List<Node> nodes = Arrays.asList(root, child1, child2);
Map<String, List<Node>> sources = nodes.stream()
.collect(groupingBy(e -> Objects.isNull(e.getPid()) ? ROOT : e.getPid()));
TreeUtils.buildTree(sources, ROOT, Node::getId, Node::setChildren);
}
}
//节点实体类
class Node {
private String id;
private String pid;
private String name;
private List<Node> children;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPid() {
return pid;
}
public void setPid(String pid) {
this.pid = pid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Node> getChildren() {
return children;
}
public void setChildren(List<Node> children) {
this.children = children;
}
}