點選檢視程式碼
import org.apache.commons.collections4.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.Function;
/**
* List -> TreeList
*/
public class TreeUtil<T, K> {
/**
* 普通的非樹形 list
*/
private List<T> list;
/**
* 樹形 list
*/
private List<T> treeList;
/**
* 節點的 id 的 getter 方法
*/
private Function<T, K> idGetterFunction;
/**
* 節點的父 id 的 getter 方法
*/
private Function<T, K> parentIdGetterFunction;
/**
* 節點的子集合的 setter 方法
*/
private BiConsumer<T, List<T>> childListSetterConsumer;
/**
* 節點的子集合的 getter 方法
*/
private Function<T, List<T>> childListGetterFunction;
/**
* 節點的層數的 setter 方法(根節點層數為 1,次根節點的層數為 2,以此類推)
*/
private FloorConsumer<T, Integer> floorSetterConsumer;
/**
* 構造方法(不設定層數)
*/
public TreeUtil(List<T> list,
Function<T, K> idGetterFunction,
Function<T, K> parentIdGetterFunction,
BiConsumer<T, List<T>> childListSetterConsumer) {
this.list = list;
this.idGetterFunction = idGetterFunction;
this.parentIdGetterFunction = parentIdGetterFunction;
this.childListSetterConsumer = childListSetterConsumer;
}
/**
* 構造方法(設定層數)
*/
public TreeUtil(List<T> list,
Function<T, K> idGetterFunction,
Function<T, K> parentIdGetterFunction,
BiConsumer<T, List<T>> childListSetterConsumer,
FloorConsumer<T, Integer> floorSetterConsumer) {
this.list = list;
this.idGetterFunction = idGetterFunction;
this.parentIdGetterFunction = parentIdGetterFunction;
this.childListSetterConsumer = childListSetterConsumer;
this.floorSetterConsumer = floorSetterConsumer;
}
/**
* 構造方法
*/
public TreeUtil(List<T> treeList, Function<T, List<T>> childListGetterFunction) {
this.treeList = treeList;
this.childListGetterFunction = childListGetterFunction;
}
/**
* 普通 list -> 樹形 list
*/
public List<T> fromListToTreeList() {
if (list.isEmpty()) {
return new ArrayList<>();
}
// 根節點集合
List<T> rootList = new ArrayList<>();
AtomicInteger atomicInteger = new AtomicInteger(1);
for (T node : list) {
// 若每個節點的 id 都不是這個節點的父id,則這個節點是根節點
if (list.stream().noneMatch(i -> idGetterFunction.apply(i).equals(parentIdGetterFunction.apply(node)))) {
rootList.add(buildTreeOfTheNode(node, 1, atomicInteger));
}
}
return rootList;
}
/**
* 樹形 list -> 普通 list
*/
public List<T> fromTreeListToList() {
List<T> list = new ArrayList<>();
if (treeList.isEmpty()) {
return list;
}
// 新增根節點
list.addAll(treeList);
// 某個層數的所有節點
List<T> listOfAFloor = new CopyOnWriteArrayList<>(treeList); // listOfAFloor: while 迴圈的入參
while (true) {
if (CollectionUtils.isEmpty(listOfAFloor)) {
break;
}
// 某個層數的所有節點的子節點(不包括孫子節點)
List<T> childListOfAFloor = new CopyOnWriteArrayList<>();
for (T t : listOfAFloor) {
List<T> childList = childListGetterFunction.apply(t);
if (CollectionUtils.isNotEmpty(childList)) {
list.addAll(childList);
childListOfAFloor.addAll(childList);
}
}
listOfAFloor = childListOfAFloor; // listOfAFloor: 賦值為 childListOfAFloor,作為下一個 while 迴圈的入參
}
return list;
}
/**
* 透過遞迴,將某個節點和他的子,孫,曾孫 ... 節點構建為樹形結構
*
* @param node 節點
* @param floor 層數
* @return 樹形結構
*/
private T buildTreeOfTheNode(T node, Integer floor, AtomicInteger atomicInteger) {
int count = atomicInteger.getAndIncrement();
if (count > 500) {
throw new RuntimeException("遞迴次數過多");
}
List<T> childList = new ArrayList<>();
if (floorSetterConsumer != null) {
floorSetterConsumer.setNodeFloor(node, floor);
}
for (T t : list) {
if (idGetterFunction.apply(node).equals(parentIdGetterFunction.apply(t))) {
childList.add(buildTreeOfTheNode(t, (floor + 1), atomicInteger));
}
}
childListSetterConsumer.accept(node, childList);
return node;
}
}
點選檢視程式碼
@Data
class Person {
/**
* id
*/
private Integer id;
/**
* 父id
*/
private Integer pId;
/**
* 名稱
*/
private String name;
/**
* 子節點集合
*/
private List<Person> sons;
/**
* 層數
*/
private Integer floor;
}
點選檢視程式碼
import java.util.ArrayList;
import java.util.List;
public class MainTest {
public static void main(String[] args) {
List<Person> list = new ArrayList<>();
Person grandFather = new Person();
grandFather.setId(1);
grandFather.setPId(0);
grandFather.setName("爺爺");
list.add(grandFather);
Person father = new Person();
father.setId(2);
father.setPId(1);
father.setName("爸爸");
list.add(father);
Person uncle_1 = new Person();
uncle_1.setId(3);
uncle_1.setPId(1);
uncle_1.setName("大叔");
list.add(uncle_1);
Person uncle_2 = new Person();
uncle_2.setId(4);
uncle_2.setPId(1);
uncle_2.setName("二叔");
list.add(uncle_2);
Person grandson = new Person();
grandson.setId(5);
grandson.setPId(2);
grandson.setName("小明");
list.add(grandson);
//TreeUtil<Node, Integer> treeUtil = new TreeUtil<>(list, Node::getId, Node::getPId, Node::setSons);
TreeUtil<Person, Integer> treeUtil = new TreeUtil<>(list, Person::getId, Person::getPId, Person::setSons, Person::setFloor);
List<Person> treeList = treeUtil.fromListToTreeList();
System.out.println(treeList);
TreeUtil<Person, Integer> unBuildTreeUtil = new TreeUtil<>(treeList, Person::getSons);
List<Person> personList = unBuildTreeUtil.fromTreeListToList();
System.out.println(personList);
}
}