ListToTreeUtil
import lombok.Data;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
public class ListToTreeUtil {
public static <T> List<Tree<T>> convertListToTree(List<T> nodeList, TreeConverter<T> converter) {
if (nodeList == null || nodeList.isEmpty()) {
return new ArrayList<>();
}
Map<Object, Tree<T>> nodeMap = new HashMap<>();
List<Tree<T>> rootNodes = new ArrayList<>();
for (T item : nodeList) {
Object itemId = converter.getItemId(item);
Tree<T> treeNode = new Tree<>(itemId, item);
nodeMap.put(itemId, treeNode);
}
for (T item : nodeList) {
Object parentId = converter.getParentId(item);
if (parentId == null || !nodeMap.containsKey(parentId)) {
Tree<T> rootNode = nodeMap.get(converter.getItemId(item));
rootNodes.add(rootNode);
} else {
Tree<T> parent = nodeMap.get(parentId);
Tree<T> childNode = nodeMap.get(converter.getItemId(item));
parent.addChild(childNode);
}
}
return rootNodes;
}
public interface TreeConverter<T> {
Object getItemId(T item);
Object getParentId(T item);
}
@Data
public static class Tree<T> {
private Object id;
private T data;
private List<Tree<T>> children;
public Tree(Object id, T data) {
this.id = id;
this.data = data;
this.children = new ArrayList<>();
}
public void addChild(Tree<T> child) {
children.add(child);
}
}
public static <T> List<T> convertListToTree(List<T> nodeList, TreeIdAccessor<T> idAccessor, TreeParentIdAccessor<T> parentIdAccessor, TreeChildrenAccessor<T> childrenAccessor, SetChildFunction<T> setChildFunction) {
if (nodeList == null || nodeList.isEmpty()) {
return new ArrayList<>();
}
Map<Object, T> nodeMap = new HashMap<>();
List<T> rootNodes = new ArrayList<>();
for (T node : nodeList) {
Object nodeId = idAccessor.getId(node);
nodeMap.put(nodeId, node);
}
for (T node : nodeList) {
Object parentId = parentIdAccessor.getParentId(node);
if (parentId == null) {
rootNodes.add(node);
} else {
T parent = nodeMap.get(parentId);
if (parent != null) {
List<T> children = childrenAccessor.getChildren(parent);
if (Objects.isNull(children)) {
children = new LinkedList<>();
setChildFunction.setChildren(parent, children);
}
children.add(node);
} else {
rootNodes.add(node);
}
}
}
return rootNodes;
}
public static <T> List<T> convertListToTreeV2(List<T> nodeList, Function<T,Object> idAccessor, Function<T,Object> parentIdAccessor, Function<T,List<T>> childrenAccessor, BiConsumer<T,List<T>> setChildFunction) {
if (nodeList == null || nodeList.isEmpty()) {
return new ArrayList<>();
}
Map<Object, T> nodeMap = new HashMap<>();
List<T> rootNodes = new ArrayList<>();
for (T node : nodeList) {
Object nodeId = idAccessor.apply(node);
nodeMap.put(nodeId, node);
}
for (T node : nodeList) {
Object parentId = parentIdAccessor.apply(node);
if (parentId == null) {
rootNodes.add(node);
} else {
T parent = nodeMap.get(parentId);
if (parent != null) {
List<T> children = childrenAccessor.apply(parent);
if (Objects.isNull(children)) {
children = new LinkedList<>();
setChildFunction.accept(parent,children);
}
children.add(node);
} else {
rootNodes.add(node);
}
}
}
return rootNodes;
}
public interface TreeIdAccessor<T> {
Object getId(T node);
}
public interface TreeParentIdAccessor<T> {
Object getParentId(T node);
}
public interface TreeChildrenAccessor<T> {
List<T> getChildren(T node);
}
public interface SetChildFunction<T> {
void setChildren(T node, List<T> childNodeList);
}
}
测试
import cn.hutool.json.JSONUtil;
import java.util.ArrayList;
import java.util.List;
public class Example {
public static void main(String[] args) throws Throwable {
List<Item> itemList = new ArrayList<>();
itemList.add(new Item("A", null));
itemList.add(new Item("B", "A"));
itemList.add(new Item("C", "A"));
itemList.add(new Item("D", "B"));
itemList.add(new Item("E", "B"));
System.out.println(JSONUtil.toJsonPrettyStr(ListToTreeUtil.convertListToTree(itemList,
Item::getNodeName,
Item::getParentNodeName,
Item::getChild,
Item::setChild
)));
System.err.println("-----------------------------------------------");
System.out.println(JSONUtil.toJsonPrettyStr(ListToTreeUtil.convertListToTreeV2(itemList,
Item::getNodeName,
Item::getParentNodeName,
Item::getChild,
Item::setChild
)));
System.err.println("-----------------------------------------------");
System.out.println();
System.out.println(JSONUtil.toJsonPrettyStr(ListToTreeUtil.convertListToTree(itemList, new ListToTreeUtil.TreeConverter<Item>() {
@Override
public Object getItemId(Item item) {
return item.getNodeName();
}
@Override
public Object getParentId(Item item) {
return item.getParentNodeName();
}
}
)));
}
}
Item
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Item {
private String nodeName;
private String parentNodeName;
private List<Item> child;
public Item(String nodeName, String parentNodeName) {
this.nodeName = nodeName;
this.parentNodeName = parentNodeName;
}
}
输出结果:
[
{
"nodeName": "A",
"child": [
{
"nodeName": "B",
"parentNodeName": "A",
"child": [
{
"nodeName": "D",
"parentNodeName": "B"
},
{
"nodeName": "E",
"parentNodeName": "B"
}
]
},
{
"nodeName": "C",
"parentNodeName": "A"
}
]
}
]
[
{
"id": "A",
"data": {
"nodeName": "A"
},
"children": [
{
"id": "B",
"data": {
"nodeName": "B",
"parentNodeName": "A"
},
"children": [
{
"id": "D",
"data": {
"nodeName": "D",
"parentNodeName": "B"
},
"children": [
]
},
{
"id": "E",
"data": {
"nodeName": "E",
"parentNodeName": "B"
},
"children": [
]
}
]
},
{
"id": "C",
"data": {
"nodeName": "C",
"parentNodeName": "A"
},
"children": [
]
}
]
}
]