列表数据结构
假设有这样一个数据集合,其列表元素结构为:
/**
* 这部分数据可能是调第三方api或者查询的数据库
*/
@Builder
@Data
public class RegionNode {
private String id; // 区域id
private String pid; // 区域父id
private String name; // 区域名称
}
数据
id | pid | name |
---|---|---|
410000 | 0 | 河南 |
410100 | 410000 | 郑州 |
410103 | 410100 | 二七区 |
410105 | 410100 | 金水区 |
410102 | 410100 | 中原区 |
410106 | 410100 | 上街区 |
将列表数据拼成一棵树
定义结构体
/**
* 返回给前端页面
*/
@Data
public class TreeNode {
private String id; // 区域id
private String pid; // 区域父id
private String name; // 区域名称
private List<TreeNode> children; // 子区域集合
public void addChild(TreeNode child){
if(this.children == null){
this.children = new ArrayList<>();
}
this.children.add(child);
}
}
转换方法
public static TreeNode convert(List<RegionNode> regionNodeList){
Map<String,TreeNode> map = new HashMap<>();
for(RegionNode regionNode : regionNodeList){
TreeNode treeNode = new TreeNode();
BeanUtils.copyProperties(regionNode, treeNode);
map.put(regionNode.getId(), treeNode);
}
TreeNode root = null;
for (Map.Entry<String, TreeNode> entry : map.entrySet()) {
// 找到根节点(把哪个作为根节点可以配置)
if("0".equals(entry.getValue().getPid())){
root = entry.getValue();
continue;
}
// 找到当前节点的父节点
TreeNode parent = map.get(entry.getValue().getPid());
if(parent != null){
parent.addChild(entry.getValue());
}
}
return root;
}
验证
public static void main(String[] args) {
List<RegionNode> regionNodeList = new ArrayList<>();
RegionNode regionNode1 = RegionNode.builder().id("410000").pid("0").name("河南").build();
RegionNode regionNode2 = RegionNode.builder().id("410100").pid("410000").name("郑州").build();
RegionNode regionNode3 = RegionNode.builder().id("410103").pid("410100").name("二七区").build();
RegionNode regionNode4 = RegionNode.builder().id("410105").pid("410100").name("金水区").build();
RegionNode regionNode5 = RegionNode.builder().id("410102").pid("410100").name("中原区").build();
RegionNode regionNode6 = RegionNode.builder().id("410106").pid("410100").name("上街区").build();
regionNodeList.add(regionNode1);
regionNodeList.add(regionNode3);
regionNodeList.add(regionNode4);
regionNodeList.add(regionNode5);
regionNodeList.add(regionNode6);
regionNodeList.add(regionNode2);
TreeNode treeNode = convert(regionNodeList);
System.out.println(treeNode);
}
结语
convert
方法中循环了2次,其实可以对regionNodeList
先根据id排序,保证上层区域在最列表的前面,可以一次循环就搞定。- 如果数据量很大的话这种方式不适合,组成一颗庞大的树给到前端页面渲染起来也会很慢。可以根据
pid
逐层查询下级列表。