单纯列表转树的逻辑我是清楚的,不管用什么实现方案,核心应该都是根据 id 找到父节点,并将当前节点添加到父节点的子节点列表属性中。
我的问题是在java 中能不能写一个通用的实现?
比如:只有一个资源实体类需要转树时,那直接写一个与资源实体类相对应的节点类,这个节点类不仅有资源实体类的所有属性,而且还多一个子节点列表属性就可以了。但如果有多个需要转换树结构的资源呢?总不能给每一个需要转换的资源实体类都创建对应的节点类吧?而且即便是只有一个,也是有弊端的,如果实体类有几百个属性,那这几百个属性还要挨个重写一遍?
我现在想到了两种方案,但各有弊端,具体如下:
第一:利用泛型,建一个通用的 TreeNode,就像这样:
public class TreeNode<T> {
private T PO;
private List<TreeNode> childList;
....
}
这样就是将实体类对象用泛型保存,子节点列表在外面单独用一个属性保存,不管有多少各类需要转换,也不管需要被转换的类型里有多少属性都可以用,但这样的话,子节点列表就和其他属性割裂开了,对前端或其他树状结构数据消费者可能是不友好。
第二:利用继承,将包含 childList 的 TreeNode 作为所有需要实现列表转树的父类。但这样的弊端就更明显了,比如有一个需要转换树节点的类已经继承了其他类怎么办?而且很多甚至大部分需要转换的都是实体类,而实体上是没有childList 的,这样做虽然没有直接改实体类,但是在父类上加了childList,其对象也是会有childList 属性的,那这还能算是一个实体对象吗是不是有点不合适?
目前就想到以上两种方案,但是都不尽人意,项目上大概率不会采用。希望有大佬提供更成熟的方案指点一二,不甚感激。
喜欢重复造轮子?这不是有现成的?干嘛不用呢?
https://doc.hutool.cn/pages/TreeUtil/
写一个泛型函数,类型就是T ,然后参数有获取父id.获取id,设置children这些
public TreeUtils(Function<T, String> parentIdFunction, Function<T, String> idFunction,
BiConsumer<T, List<T>> setChildrenFunction, Function<T, List<T>> getChildrenFunction) {
this.parentIdFunction = parentIdFunction;
this.idFunction = idFunction;
this.setChildrenFunction = setChildrenFunction;
this.getChildrenFunction = getChildrenFunction;
}
大体这个意思,然后你再写个函数,扔个list,去处理就行,反正处理tree的本质就是塞children
你都想到继承了,那为啥不多考虑一下,试试接口?
再一个咱们反射不能用啊?
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
public class TreeTest {
public static void main(String[] args) throws Exception {
List<User> users = new ArrayList<>();
users.add(new User("1","湖南省",null));
users.add(new User("2","广东省",null));
users.add(new User("3","长沙市","1"));
users.add(new User("4","深圳市","2"));
users.add(new User("5","岳麓区","3"));
users.add(new User("6","望城坡街道","5"));
users.add(new User("7","湘潭市","1"));
List<? extends TreeNode> tree = tree(users);
ObjectMapper objectMapper = new ObjectMapper();
System.out.println(objectMapper.writeValueAsString(tree));
}
public static <T extends TreeNode> List<T> tree(List<T> list){
List<T> headerNodes = new ArrayList<>();
// 构造顶级节点
for (TreeNode tree : list) {
if(StringUtils.isEmpty(tree.getPid())){
headerNodes.add((T) tree.newInstance());
}
}
// 循环将当前节点加入到父节点的集合中
for (T t : list) {
parentNodeAddChild(t,headerNodes);
}
return headerNodes;
}
private static <T extends TreeNode> void parentNodeAddChild(TreeNode<T> node,List<T> parentNodes){
for (TreeNode treeNode : parentNodes) {
// 找到父节点,直接加入子集并且结束循环
if(StringUtils.equals(node.getPid(),treeNode.getId())){
treeNode.getChildList().add(node);
break;
}
// 递归循环父节点
parentNodeAddChild(node, treeNode.getChildList());
}
}
}
interface TreeNode<T>{
String getPid();
String getId();
List<T> getChildList();
String getText();
<T extends TreeNode> T newInstance();
}
@Data
@JsonIgnoreProperties({"name","children"})
class User implements TreeNode<User>{
public User(String id, String name, String pid) {
this.id = id;
this.name = name;
this.pid = pid;
this.children = new ArrayList<>();
}
@Override
public String getPid() {
return pid;
}
@Override
public List<User> getChildList() {
return children;
}
@Override
public String getText() {
return name;
}
@Override
public User newInstance() {
return new User(id,name,pid);
}
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", getText()='" + name + '\'' +
", pid='" + pid + '\'' +
", children=" + children +
'}';
}
private String id;
private String name;
private String pid;
private List<User> children;
}
如下图: 根据某一个相同的元素合并单元格,然后又有树形的表格该怎么做? 各位大佬能否给个demo
问题内容: 我在列表中有一个字符串路径集合,例如[“ x1 / x2 / x3”,“ x1 / x2 / x4”,“ x1 / x5”]。我需要从该列表构造一个树状结构,可以对其进行迭代以获得漂亮的打印树。像这样 有什么想法/建议吗?我认为可以通过处理字符串列表来首先解决该问题。编辑:选择的正确答案是一种优雅的实现,其他建议也很好。 问题答案: 遵循可访问树的幼稚实现的实现: 访客模式的界面: 访
一、想要实现的效果 二、我的代码 public class People { } public static void main(String[] args) { 三、代码执行结果 四、解释 我递归用的少,用起来有点不达意。上面自己写的递归方法虽然能实现递归效果,但问题很大。 4.1、我的方法返回的只是命中项,而不是一个树的结构(除非第一层就命中了)。 4.2、返回的树里没有剔除未命中项。 上述两
蓝牙设备对象 证书对象 证书主体对象 Cookie对象 崩溃报告对象 桌面捕获源对象 显示器对象 打印机信息对象 文件过滤器对象 最近使用的项目 常用列表项 CPU使用率对象即程序占用的CPU资源 IO值对象 内存信息对象 进程内存信息对象 内存使用详细信息 Mime类型缓冲区 矩形对象 删除客户端证书对象 删除密码对象 Scrubber项对象 分段控制对象
我现在正在做一个Java-Spring启动项目。我有一个API_endpoint,有4个完全相同的字段。所以字段1(用户名)、字段2(名字)、字段3(姓氏)和字段4。字段1-3很简单,我可以通过等方式分配它们。 但Field4则不同。这是一个嵌套的结构,它有时会有所不同。 例如,在一个请求中,它类似于: 下一次就像 这可能多达200个字段。 换句话说:Field4是一个复杂的嵌套结构,可以在每个请
我有一个带有< code>parent字段的“page”对象列表。该父字段引用了列表中的另一个对象。我想从基于此字段的列表中创建一个树层次结构。 以下是我的原始列表: 我想把它转换成这样的树形结构: 我希望有一个可重用的函数,我可以随时对任意列表调用它。有谁知道处理这个问题的好方法吗?任何帮助或建议将不胜感激!