TreeUtil

点击查看代码
 
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);

    }

}

posted @ 2024-11-09 12:43  凛冬雪夜  阅读(25)  评论(0)    收藏  举报