前言
我們在平時開發中,難免會遇到一些list轉tree的情況,例如省市區及區下面的一些區域,就需要用到樹的形式,而我們的原始數據爲了存儲方便一般拿出來都是list的形式,這時候就需要轉換
構造對象
這裏的pId表示上級節點的id,設定頂級節點的pId = 0
@Data
public class TreeNode {
private Long id;
private Long pId;
private String name;
private List<TreeNode> child;
}
分析邏輯
入參是一個沒有chid的List< TreeNode>,包含所有層級的節點
- 先把list按照pid分組,value則是pid對應的child
- 構造循環的條件:當沒有下級節點的時候
- 循環內封裝數據
實現方法
public static List<TreeNode> buildTree(List<TreeNode> list) {
// 數據校驗
if (CollectionUtils.isEmpty(list)) {
return Collections.emptyList();
}
// 過濾掉null並按照pId分組
Map<Long, List<TreeNode>> map = list.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(TreeNode::getPId));
// 再校驗一次
if (MapUtils.isEmpty(map)) {
return Collections.emptyList();
}
// 獲取一級節點,樹的根節點
List<TreeNode> res = map.get(0L);
// 父級節點
List<TreeNode> parent = res;
while (true) {
List<TreeNode> temp = new ArrayList<>();
// 遍歷父級節點
for (TreeNode treeNode : parent) {
Long pId = treeNode.getId();
// 封裝child
if (map.containsKey(pId)) {
List<TreeNode> child = map.get(pId);
treeNode.setChild(child);
temp.addAll(child);
}
}
// 直到沒有子節點
if (CollectionUtils.isEmpty(temp)) {
break;
}
// 繼續下一次循環
parent = temp;
}
return res;
}
有點沒有看明白,驗證確實可用。
TreeUtils.java
package com.imddy.sc.utils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.springframework.util.CollectionUtils;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class TreeUtils {
public static void main(String[] args) throws JsonProcessingException {
TreeNode node4 = new TreeNode(4, "宜昌市", 1);
TreeNode node5 = new TreeNode(5, "上海市", 0);
TreeNode node6 = new TreeNode(6, "靜安區", 5);
TreeNode node7 = new TreeNode(7, "青浦區", 5);
TreeNode node8 = new TreeNode(8, "黃浦區", 5);
TreeNode node16 = new TreeNode(16, "渝中區", 10);
TreeNode node17 = new TreeNode(17, "渝北區", 10);
TreeNode node14 = new TreeNode(14, "武侯區", 11);
TreeNode node15 = new TreeNode(15, "高新區", 11);
TreeNode node18 = new TreeNode(18, "沙坪壩區", 10);
TreeNode node9 = new TreeNode(9, "四川省", 0);
TreeNode node10 = new TreeNode(10, "重慶市", 0);
TreeNode node11 = new TreeNode(11, "成都市", 9);
TreeNode node12 = new TreeNode(12, "達州市", 9);
TreeNode node13 = new TreeNode(13, "通川區", 12);
TreeNode node0 = new TreeNode(0, "中國", -1);
TreeNode node1 = new TreeNode(1, "湖北省", 0);
TreeNode node2 = new TreeNode(2, "武漢市", 1);
TreeNode node3 = new TreeNode(3, "洪山區", 2);
List<TreeNode> list = new ArrayList<>();
list.add(node3);
list.add(node4);
list.add(node1);
list.add(node2);
list.add(node5);
list.add(node6);
list.add(node0);
list.add(node7);
list.add(node8);
list.add(node9);
list.add(node10);
list.add(node11);
list.add(node12);
list.add(node13);
list.add(node14);
list.add(node15);
list.add(node16);
list.add(node17);
list.add(node18);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(Include.NON_EMPTY);
objectMapper.setSerializationInclusion(Include.NON_NULL);
List<TreeNode> nodes99 = listToTreeByMap(list, 9);
System.out.println(JSON.toJSONString(nodes99));
System.out.println(objectMapper.writeValueAsString(nodes99));
System.out.println("-----------------------------------------------------------------------");
List<TreeNode> nodes100 = listToTreeByMap(list, 10);
System.out.println(JSON.toJSONString(nodes100));
System.out.println(objectMapper.writeValueAsString(nodes100));
System.out.println("-----------------------------------------------------------------------");
List<TreeNode> nodes101 = listToTreeByMap(list, 0);
System.out.println(JSON.toJSONString(nodes101));
System.out.println(objectMapper.writeValueAsString(nodes101));
System.out.println("-----------------------------------------------------------------------");
List<TreeNode> nodes102 = listToTreeByMap(list, -1);
System.out.println(JSON.toJSONString(nodes102));
System.out.println(objectMapper.writeValueAsString(nodes102));
}
public static List<TreeNode> listToTreeByMap(List<TreeNode> list, Integer pid) {
// 數據校驗
if (CollectionUtils.isEmpty(list)) {
return Collections.emptyList();
}
// 過濾掉null並按照pId分組
Map<Integer, List<TreeNode>> map = list.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(TreeNode::getPid));
// 再校驗一次
if (CollectionUtils.isEmpty(map)) {
return Collections.emptyList();
}
// 獲取一級節點,樹的根節點
List<TreeNode> res = map.get(pid);
// 父級節點
List<TreeNode> parent = res;
while (true) {
List<TreeNode> temp = new ArrayList<>();
// 遍歷父級節點
for (TreeNode treeNode : parent) {
Integer pId = treeNode.getId();
// 封裝child
if (map.containsKey(pId)) {
List<TreeNode> child = map.get(pId);
treeNode.setChildren(child);
temp.addAll(child);
}
}
// 直到沒有子節點
if (CollectionUtils.isEmpty(temp)) {
break;
}
// 繼續下一次循環
parent = temp;
}
return res;
}
}
對應的TreeNode.java
package com.imddy.sc.utils;
import java.util.List;
import lombok.Data;
@Data
public class TreeNode {
private Integer id;
private String city;
private Integer pid;
private List<TreeNode> children;
public TreeNode(Integer id, String city, Integer pid) {
this.id = id;
this.city = city;
this.pid = pid;
}
}