首页 > 其他分享 >TreeUtil

TreeUtil

时间:2024-11-09 12:41:04浏览次数:1  
标签:List list private Person TreeUtil new 节点

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

    }

}

标签:List,list,private,Person,TreeUtil,new,节点
From: https://www.cnblogs.com/SetariaViridis/p/18536630

相关文章

  • treeutil工具类
    原文链接/***@Description:树操作方法工具类*@Author:公众号:赵侠客*@Copyright:Copyright(c)赵侠客*@Date:2024-07-2210:42*@Version:1.0*/publicclassTreeUtil{/***将list合成树**@paramlist需要合成树的List*......
  • hutool 使用 TreeUtil 查询树型结构
    之前写过一篇用stream流实现查询树型结构的文章,现在以hutool中的TreeUtil再来实现一次,之前的帖子JavaStream流实现递归查询树型结构查询出所有数据,用父节点递归查询出所有子节点数据/***封装备注分类集合**@paramremarkTypeList备注分类集合*......
  • hutool的树形工具类-TreeUtil
    packagecom.fayi.hutool.TreeUtil;importcn.hutool.core.lang.tree.Tree;importcn.hutool.core.lang.tree.TreeNodeConfig;importcn.hutool.core.lang.tree.TreeUtil;importcn.hutool.json.JSONUtil;importlombok.AllArgsConstructor;importlombok.Data;impor......
  • 开发用工具类2.0:无侵入式的树形状工具类TreeUtils
    packagecn.jow.util;importjava.util.*;importjava.util.function.Function;importjava.util.stream.Collectors;/***无侵入方式处理对象集合,树形状结构数......
  • JAVA8自带TreeUtils
        tree.json{"code":200,"msg":"操作成功","data":[{"id":"310000","name":"电子商务","parentId":"000000"}......
  • TreeUtils工具类一行代码实现列表转树【第三版优化】 三级菜单 三级分类 附视频
    一、序言在日常一线开发过程中,总有列表转树的需求,几乎是项目的标配,比方说做多级菜单、多级目录、多级分类等,有没有一种通用且跨项目的解决方式呢?帮助广大技术朋友给业务瘦......
  • TreeUtils工具类一行代码实现列表转树 实战Java8 三级菜单 三级分类 附视频
    一、序言在日常一线开发过程中,总有列表转树的需求,几乎是项目的标配,比方说做多级菜单、多级目录、多级分类等,有没有一种通用且跨项目的解决方式呢?帮助广大技术朋友给业务瘦......
  • Hutool工具-TreeUtil封装树形结构数据,你用过了吗
    在开发过程中,必定会遇到树形结构的数据,一般都是后端直接从库里查询出来然后自定义方法去封装成树形树形返回给前端。其实Hutool工具类也提供了这个方法,这种方式使用起来也......