首页 > 其他分享 >非递归快速构建树-注解版

非递归快速构建树-注解版

时间:2024-09-27 11:25:27浏览次数:6  
标签:java 递归 Tree List private field 构建 import 注解

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 树注解工具类
 *    父子关系构建树形数据结构
 * @param <T>
 */
public class TreeAnnoUtil<T> {

    private Field[] fields;

    public TreeAnnoUtil(Class<T> clazz) {
        this.fields = clazz.getDeclaredFields();
    }

    /**
     * 构建树
     * @param orginals
     * @return
     */
    public List<T> buildTree(List<T> orginals) {
        List<T> result = null;
        try {
            Map<String, T> dataMap = this.addToMap(orginals);
            result = this.doBuildTree(dataMap);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 原始数据添加到map集合
     * @param orginals
     * @return
     */
    private Map<String, T> addToMap(List<T> orginals) throws IllegalAccessException {
        // 创建Map,将原数据的 id 作为 key,原数据对象作为 value
        Map<String, T> dataMap = new LinkedHashMap<>();
        for (T t : orginals) {
            for (Field field : fields){
                Tree tree = field.getAnnotation(Tree.class);
                if(tree != null && tree.isId()){
                    field.setAccessible(true);
                    dataMap.put(field.get(t)+"", t);
                    break;
                }
            }
        }
        return dataMap;
    }

    /**
     * 执行构件树操作
     * @param dataMap
     * @return
     * @throws Exception
     */
    private List<T> doBuildTree(Map<String, T> dataMap) throws IllegalAccessException {
        List<T> result = new ArrayList<>();
        for (Map.Entry<String, T> entry : dataMap.entrySet()) {
            T t = entry.getValue();
            String parentId = null;
            for (Field field : fields){
                Tree tree = field.getAnnotation(Tree.class);
                if(tree != null && tree.isParentId()){
                    field.setAccessible(true);
                    Object parentIdObj = field.get(t);
                    if(parentIdObj != null){
                        parentId = field.get(t)+"";
                    }
                    break;
                }
            }
            // 如果是根节点,直接添加到结果集合中
            if (parentId == null || "0".equals(parentId)) {
                result.add(t);
            } else {
                // 如果不是根节点,找到父节点,然后添加到父节点的子节点中
                T parentT = dataMap.get(parentId);
                for (Field field : fields){
                    Tree tree = field.getAnnotation(Tree.class);
                    if(tree != null && tree.isChildren()){
                        field.setAccessible(true);
                        List<T> children = (List<T>) field.get(parentT);
                        children.add(t);
                        break;
                    }
                }
            }
        }
        return result;
    }

    // 行号,初始值为 0
    private static ThreadLocal<Integer> rowNoThreadLocal = ThreadLocal.withInitial(() -> 0);

    /**
     * 打印 树名称,可模拟树结构
     *     使用完 rowNoThreadLocal 记得关闭
     * @param list
     * @param level
     */
    private void printTree(List<OrgVo> list, int level){
        String space = "";
        for (int i = 0; i < level; i++) {
            space = "  " + space;
        }

        //递归一次,层级+1;
        level++;

        for (int i = 0; i < list.size(); i++) {
            OrgVo orgVo = list.get(i);
            String label = orgVo.getLabel();
            List<OrgVo> children = orgVo.getChildren();

            int rowNo = rowNoThreadLocal.get() + 1;// 行号
            rowNoThreadLocal.set(rowNo);
            System.out.println(space + label + "[层级" + (level) + "-行号" + rowNo + "]");

            if(children.size() > 0){
                printTree(children, level);
            }
        }
    }

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        TreeAnnoUtil treeAnnoUtil = new TreeAnnoUtil(OrgVo.class);
        List<OrgVo> orginals = new ArrayList<>();

        OrgVo rootOrgVo = new OrgVo();
        rootOrgVo.setOrgId(-1);
        rootOrgVo.setLabel("name" + 0);
        rootOrgVo.setOrgPid(0);
        rootOrgVo.setOrderNo(0);
        orginals.add(rootOrgVo);

        for (int i = 1; i <= 5; i++) {
            OrgVo orgVo = new OrgVo();
            orgVo.setOrgId(i);
            orgVo.setLabel("name" + i);
            orgVo.setOrgPid(-1);
            orgVo.setOrderNo(i);
            orginals.add(orgVo);
        }
        for (int i = 6; i <= 10; i++) {
            OrgVo orgVo = new OrgVo();
            orgVo.setOrgId(i);
            orgVo.setLabel("name" + i);
            orgVo.setOrgPid(1);
            orgVo.setOrderNo(i);
            orginals.add(orgVo);
        }
        for (int i = 11; i <= 15; i++) {
            OrgVo orgVo = new OrgVo();
            orgVo.setOrgId(i);
            orgVo.setLabel("name" + i);
            orgVo.setOrgPid(6);
            orgVo.setOrderNo(i);
            orginals.add(orgVo);
        }
        for (int i = 16; i <= 20; i++) {
            OrgVo orgVo = new OrgVo();
            orgVo.setOrgId(i);
            orgVo.setLabel("name" + i);
            orgVo.setOrgPid(5);
            orgVo.setOrderNo(i);
            orginals.add(orgVo);
        }
        for (int i = 21; i <= 25; i++) {
            OrgVo orgVo = new OrgVo();
            orgVo.setOrgId(i);
            orgVo.setLabel("name" + i);
            orgVo.setOrgPid(15);
            orgVo.setOrderNo(i);
            orginals.add(orgVo);
        }
        for (int i = 26; i <= 30; i++) {
            OrgVo orgVo = new OrgVo();
            orgVo.setOrgId(i);
            orgVo.setLabel("name" + i);
            orgVo.setOrgPid(23);
            orgVo.setOrderNo(i);
            orginals.add(orgVo);
        }
        System.out.println("数据大小:"+orginals.size());
        List<OrgVo> treeNodes = treeAnnoUtil.buildTree(orginals);
        System.out.println("耗时:"+(System.currentTimeMillis() - start));
        treeAnnoUtil.printTree(treeNodes, 0);

        rowNoThreadLocal.remove();
//        try {
//            ObjectMapper objectMapper = new ObjectMapper();
//            String json = objectMapper.writeValueAsString(treeNodes);
//            System.out.println(json);
//        } catch (JsonProcessingException e) {
//            e.printStackTrace();
//        }
    }

}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface Tree {

    // 是否是 id
    boolean isId() default false;

    // 是否是 parentId
    boolean isParentId() default false;

    // 是否是 children
    boolean isChildren() default false;


}
import lombok.Data;

import java.util.ArrayList;
import java.util.List;

@Data
public class OrgVo {

    @Tree(isId = true)
    private int orgId;

    private String label;

    @Tree(isParentId = true)
    private int orgPid;

    private int orderNo;

    @Tree(isChildren = true)
    private List<OrgVo> children = new ArrayList<>();

}

 

标签:java,递归,Tree,List,private,field,构建,import,注解
From: https://www.cnblogs.com/sunhao1234/p/18435319

相关文章

  • 从‘盲管’到‘智网’,精准构建排水管网监测方案
    在城市错综复杂的基础设施网络中,排水管网作为城市的“血脉”,其高效、稳定运行直接关系到城市生活的安宁与财产的安全。面对日益频繁的雨季挑战与气候变化的不确定性,传统“盲管”管理模式已难以满足现代城市治理的需求。排水管网监测方案通过集成高精度传感器与低功耗远程采集终端,实......
  • 使用 LoadBalancerClient 和 @LoadBalanced 注解需要注意的事项
    使用LoadBalancerClient负责均衡客户端时:情况一:@BeanpublicRestTemplaterestTemplate(){returnnewRestTemplate();}@RestControllerpublicclassConsumerController{@AutowiredprivateRestTemplaterestTemplate;@Autowired......
  • 手把手教你在Linux上构建Electron
    开发electron最大的特点就是可以使用web技术来开发跨平台应用,大部分开发都是在windows/mac上开发的electron应用,我使用的是electorn-builder来构建应用,官网提供支持在windows上使用docker来实现Linux版本的构建。可以直接在Linux服务器上完成构建:构建Linux环境的electron......
  • 旭升集团携手纷享销客,构建全方位客户关系管理平台
    宁波旭升集团股份有限公司(以下简称“旭升集团”)自2003年成立,总部位于中国宁波,集团设有压铸、锻造、挤压、集成四大事业部,在亚洲、欧洲、美洲等地均设立研发中心及制造基地,产品主要覆盖新能源汽车的电驱动系统、电控系统、电池系统、底盘悬挂系统及高性能车身系统等。凭借领先的制......
  • 通过构建具有依赖关系的后端框架来学习 Nodejs
    我在github上为每个尝试涉足后端开发世界(不仅仅是Node.js)的人创建了一本开源(免费)书籍您还可以在本书的网站上以更易于理解的方式访问内容-CacheLane-LearnNode.jstheHardWay这将需要很长时间来构建完成版本(几个月),但不用担心,我已经承诺并承诺每天都会添加新内容。因此,即......
  • 构建可扩展的 Azure 静态 Web 应用程序来处理高流量网站
    tl;dr:azurestaticwebapps的免费托管计划可能无法满足高流量需求。通过最小化和压缩资产、优化图像加载、实施缓存、使用企业级边缘和自动缩放来扩展这些应用程序,以增强全球用户的性能、安全性和效率。在当今的软件开发世界中,您的应用程序不仅服务于本地社区,还覆盖来自全球各......
  • 构建 JavaScript 代码:可读性和可维护性的最佳实践
    欢迎回到我们的javascript世界之旅!在这篇博文中,我们将深入探讨构建javascript代码的基本方面。正确的代码结构对于可读性、可维护性和协作至关重要。我们将介绍代码结构、语句、分号和注释。让我们开始吧!代码结构结构良好的javascript代码库易于阅读、理解和维护。以......
  • 构建动态配色游戏:全面概述
    介绍在当今快节奏的数字世界中,创建引人入胜的交互式Web应用程序的能力是一项非常有价值的技能。为了提高我在前端开发和算法问题解决方面的熟练程度,我接受了构建颜色匹配游戏的挑战。这个项目不仅让我展示了我的技术能力,还为用户提供了愉快的教育体验。本文深入探讨了游戏背后的......
  • 我的 Code Alpha 实习经历:构建项目并获得实践技能
    简介开始在CodeAlpha实习是一次令人兴奋的机会,可以检验我的前端开发技能。作为实习的一部分,我被分配了三项关键任务:创建图像库、构建基本计算器以及开发自己的作品集网站。这些项目让我能够将我的HTML、CSS和JavaScript知识应用到现实场景中,这种体验既充满挑战又富有回报。......
  • 激活数据中台:构建数据飞轮的实践之路
    在当今数据驱动的商业环境中,企业越来越重视数据的收集、存储和分析。然而,真正的挑战在于如何将这些数据转化为有价值的业务洞察以及实现数据的实际应用,也就是所谓的“激活数据”。为了有效地实现这一转化,"数据飞轮"概念应运而生,它不仅仅是技术的革新,更是企业文化和运营模式的全面革......