网站首页 > 技术文章 正文
背景
最近项目上有一个需求,在网页上的nav菜单需要展示成树形结构,还有很多数据也要展示树形结构,所以说需要封装一个公共方法来将对象List转为Tree树形数据结构。
挖坑
在第一次做的时候给自己挖了一个大坑,请先看代码
public final List<Map<String, Object>> listToTree(String parentId, List<TaskEntity> list){
List<Map<String, Object>> maps = new ArrayList<>();
for (TaskEntity task : list){
if (StringUtils.isBlank(parentId) && StringUtils.isBlank(task.getParentId())){
Map<String, Object> map = JSON.parseObject(JSON.toJSONString(task), Map.class);
map.put("children", listToTree(task.getId(), list));
maps.add(map);
} else if (StringUtils.isNotBlank(parentId) && StringUtils.isNotBlank(task.getParentId()) && parentId.equals(task.getParentId())){
Map<String, Object> map = JSON.parseObject(JSON.toJSONString(task), Map.class);
map.put("children", listToTree(task.getId(), list));
maps.add(map);
}
}
return maps;
}
但是这种方法必须要传一个顶级数据的parentId,一般来说,最上级的数据parentId为null,直接调用这个方法传入parentId为null就可以,但是假如说我查询出一个list,但是这个list的没有最上级对象呢,那就不确定list中的哪个对象是最顶级,那这个parentId参数传什么呢?
填坑
首先讲一下思路,首先坑定是查出来一个list对象集合,然后找出list中最顶级的对象list,然后循环顶级list,然后找到list中含有parentId为当前循环到的顶级对象id的下一级对象List,加到当前循环的顶级对象的“children”属性中,children也是一个list集合,然后递归循环,直到取出所有数据转为Tree,下面看代码。
- 对象List转为Tree树形结构的方法
/**
* 对象List转为Tree树形结构
* @param entityList 数据List
* @param parentFileName 用作上级ID的属性名
* @return
*/
public final List<Map<String, Object>> listToTree(List<T> entityList, String parentFileName){
List<Map<String, Object>> mapList = new ArrayList<>();
List<T> topList = getTopList(entityList, parentFileName);
topList.forEach(entity -> {
Map<String, Object> map = JSON.parseObject(JSON.toJSONString(entity, SerializerFeature.WriteMapNullValue), Map.class);
if (!map.containsKey(parentFileName)) throw new NullPointerException("父级ID字段:" + parentFileName + " 不存在于对象中");
map.put("children", getChildren(entity, entityList, parentFileName));
mapList.add(map);
});
return mapList;
}
- 得到最顶级的数据List
/**
* 得到最顶级的数据List
* @param entityList
* @param parentFileName
* @return
*/
private final List<T> getTopList(List<T> entityList, String parentFileName){
List<T> topList = new ArrayList<>();
entityList.forEach(topEntity -> {
AtomicBoolean isParent = new AtomicBoolean(true);
Map<String, Object> topMap = JSON.parseObject(JSON.toJSONString(topEntity, SerializerFeature.WriteMapNullValue), Map.class);
entityList.forEach(entity -> {
if (!topMap.containsKey(parentFileName)) throw new NullPointerException("父级ID字段:" + parentFileName + " 不存在于对象中");
if (entity.getId().equals(topMap.get(parentFileName))){
isParent.set(false);
}
});
if (isParent.get()){
topList.add(topEntity);
}
});
return topList;
}
- 递归获取子级List,这里是个递归方法(方法中会调用这个方法本身)
private final List<Map<String, Object>> getChildren(T parent, List<T> entityList, String parentFileName){
List<Map<String, Object>> mapList = new ArrayList<>();
entityList.forEach(item -> {
Map<String, Object> map = JSON.parseObject(JSON.toJSONString(item, SerializerFeature.WriteMapNullValue), Map.class);
if (!map.containsKey(parentFileName)) throw new NullPointerException("父级ID字段:" + parentFileName + " 不存在于对象中");
if (parent.getId().equals(map.get(parentFileName))){
map.put("children", getChildren(item, entityList, parentFileName));
mapList.add(map);
}
});
return mapList;
}
总结
- 具体实现思路就是:
- 得到最顶级对象List;
- 循环最顶级List并调用递归方法;
- 递归方法中在调用本身;
- 最后获得一个树形的Map集合。
注意
以上方法是封装在通用CRUD的service层的,项目中用到了MybatisPlus,然后继承MybatisPlus中的通用CRUD二次封装了一下,代码中的“T”为对象中的泛型,所以以上代码只是给大家提供一下思路,防止自己挖坑。方法可能无法直接使用到你的项目中,还是需要你自己看下,捋一捋思路的。祝你好运吧!!!
猜你喜欢
- 2024-10-18 【Python】map函数的常见用法,你知道多少?
- 2024-10-18 Python 中的数据可视化:将列表转换为图形
- 2024-10-18 Java 把一个 List 转换为字符串(java list转成字符串)
- 2024-10-18 Java Stream API:将线性集合添加到Map,键为对象属性
- 2024-10-18 SpringBoot读取配置文件中的数据到map和list
- 2024-10-18 「Java」咦,它就是Map和List的儿子吧
- 2024-10-18 一日一技:举例说明python中的map()方法
- 2024-10-18 详解 Python Map 函数(python map函数的用法)
- 2024-10-18 你应该知道的Java Map 的七个常见问题!
- 2024-10-18 Java核心数据结构(List、Map、Set)原理与使用技巧
- 最近发表
- 标签列表
-
- cmd/c (64)
- c++中::是什么意思 (83)
- 标签用于 (65)
- 主键只能有一个吗 (66)
- c#console.writeline不显示 (75)
- pythoncase语句 (81)
- es6includes (73)
- sqlset (64)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- chromepost (65)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- & (66)
- java (73)
- js数组插入 (83)
- linux删除一个文件夹 (65)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)