• java请求接口接收树形结构数据丢失问题


    背景:

    我们前后端交互可能会涉及到树形结构数据

    1,大多数设计,定义树结构基类

    package com.yw.framework.tree;
    import lombok.Data;
    
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
    
    /**
     * 功能描述: <结构树>
     * 〈〉
     *
     * @Author: zl
     * @Date: 2021/10/15 9:15
     */
    @Data
    public class Node {
    
        
        protected String id;
    
        protected String parentId;
    
        protected String name;
    
        protected List<Node> children = new ArrayList<>();
    
        protected String description;
    
        protected int rank = 0;
    
    }

    2,不同父结构数据类型继承即可

    @Data
    public static class AbilityNode extends Node {
    
        private Double weight;
    
        private List<AbilityQuotaResp> abilityQuotaRespList;
    
    }

    3,构建工具类

    package com.yw.framework.tree;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @Author zl
     * @Description 树形构造处理工具类
     *
     * @Date 2021/6/1 9:12
     */
    public class BuildTree {
    
        /**
         * 功能描述: <生成树结构>
         * 〈〉
         *
         * @Param: [T]
         * @Author: zl
         * @Date: 2021/6/1 9:10
         */
        public static List<Node> buildTree(List<? extends Node> nodeList) {
            List<Node> nodes = new ArrayList<>();
            for (Node node : nodeList) {
                String parentId = node.getParentId();
                if (parentId == null || "".equals(parentId)) {
                    nodes.add(node);
                    continue;
                }
                for (Node parent : nodeList) {
                    if (parent.getId().equals(parentId)) {
                        List<Node> parentList = parent.getChildren();
                        if (parentList == null) {
                            parentList = new ArrayList<>();
                            parentList.add(node);
                            parent.setChildren(parentList);
                        } else {
                            parentList.add(node);
                        }
                    }
                }
            }
            return nodes;
        }
    
    
        /**
         * 给树节点设置层级rank标识
         *
         * @param nodes
         */
        public static void setLevel(List<Node> nodes) {
            for (Node node : nodes) {
                String parentId = node.getParentId();
                if (parentId == null || "".equals(parentId)) {
                    node.setRank(1);
                    dfsLevel(node);
                }
            }
    
        }
    
        /**
         * 递归遍历节点数
         * @param node
         */
        public static void dfsLevel(Node node) {
            List<Node> children = node.getChildren();
            if (children!=null) {
                for (Node child : children) {
                    child.setRank(node.getRank() + 1);
                    dfsLevel(child);
                }
            }
    
        }
    
        /**
         * 获取树的最大层级
         *
         * @param nodes
         * @return
         */
        public static int maxLevel(List<Node> nodes,int maxlevel) {
            for (Node node : nodes) {
                maxlevel = Math.max(node.getRank(), maxlevel);
                if (node.getChildren()!=null) {
                    return maxLevel(node.getChildren(), maxlevel);
                }
            }
            return maxlevel;
        }
    
        /**
         * 获取树的某一层级所有节点
         *
         * @param nodes
         * @param level
         * @return
         */
        public static List<Node> getLevelNode(List<Node> nodes, int level, List<Node> nodeList) {
            for (Node node : nodes) {
                if (node.getRank() == level) {
                    nodeList.add(node);
                }
                if (node.getChildren()!=null) {
                    getLevelNode(node.getChildren(), level, nodeList);
                }
            }
            return nodeList;
        }
    
        /**
         * 获取树的所有叶子节点
         *
         * @param nodes
         * @return
         */
        public static List<Node> getLeafNode(List<? extends Node> nodes, List<Node> leafNode) {
    
            for (Node node : nodes) {
                if (node.getChildren() == null || node.getChildren().size() == 0) {
                    leafNode.add(node);
                } else {
                    getLeafNode(node.getChildren(), leafNode);
                }
            }
            return leafNode;
        }
    
        /**
         * 删除给定的叶子节点
         * @param nodes
         * @param ids
         * @param deleteSize
         * @return
         */
        public static int deleteLeafNode(List<Node> nodes, String[] ids, int deleteSize) {
    
            boolean b = nodes.removeIf(node -> {
                if ((node.getParentId() == null || "".equals(node.getParentId())) && (node.getChildren() == null || node.getChildren().size() == 0)) {
                    boolean isDelete = true;
                    for (int i = 0; i < ids.length; i++) {
                        if (ids[i].equals(node.getId())) {
                            isDelete = false;
                            break;
                        }
                    }
                    return isDelete;
                }
                return false;
    
            });
            if (b) {
                deleteSize++;
            }
    
            for (Node node : nodes) {
                if (node.getChildren() == null || node.getChildren().size() == 0) {
                    boolean isDelete = true;
                    for (int i = 0; i < ids.length; i++) {
                        if (ids[i].equals(node.getId())) {
                            isDelete = false;
                        }
                    }
                    if (isDelete) {
                        deleteSize++;
                        for (Node parent : nodes) {
                            if (parent.getId().equals(node.getParentId())) {
                                parent.getChildren().remove(node);
                                break;
                            }
                        }
                    }
                } else {
                    return deleteLeafNode(node.getChildren(), ids, deleteSize);
                }
            }
            return deleteSize;
        }
    
    }

    4,这样作为后端返回给前端设计没有问题

    5,但是,如果是接收前端树形结构就会出现问题,接收的树结构的子节点数据都没有继承类中定义的数据

    例如这样一个结构数据:

        "abilityNodeList": [
          {
            "id": "1",
            "elementId": "能力",
            "parentId": "",
            "name": "侦查能力",
            "children": [
              {
                "id": "5d0c25bfb00f4120bb56ecee1f16a20b","parentId": "1",
                "name": "111",
                "children": [],
                "description": "111",
                "rank": 0,
                "weight": 0.2,
                "abilityQuotaRespList": []
              },
              {
                "id": "19859ac711964779aabf453fae7aa890","parentId": "1",
                "name": "222",
                "children": [],
                "description": "",
                "rank": 0,
                "weight": 0.2,
                "abilityQuotaRespList": []
              }
            ],
            "description": "侦查能力",
            "rank": 0,
            "weight": 0.2,
            "abilityQuotaRespList": [
              {
                "id": "6",
                "name": "能力指标6",
                "weight": 0.8,
                "contribution": 0
              },
              {
                "id": "7",
                "name": "能力指标7",
                "weight": 0.6,
                "contribution": 0
              }
            ]
          },
          {
            "id": "3","parentId": "",
            "name": "预警能力",
            "children": [],
            "description": "预警能力",
            "rank": 0,
            "weight": 0.2,
            "abilityQuotaRespList": []
          },
          {
            "id": "2","parentId": "",
            "name": "通信能力",
            "children": [],
            "description": "通信能力",
            "rank": 0,
            "weight": 0.2,
            "abilityQuotaRespList": [
              {
                "id": "3",
                "name": "海上通信",
                "weight": 0.4,
                "contribution": 0.1
              },
              {
                "id": "4",
                "name": "地面通信",
                "weight": 0.4,
                "contribution": 0.1
              }
            ]
          }
        ]

    请求过来之后,除了根节点数据,所有子节点都没有weight和abilityQuotaRespList属性以及数据子节点默认还是基类(Node)类型

    6,最后,请求数据 树形结构类型不能用继承

    可这样直接设计,即定制化设计:

    package com.yw.module.abilitycontribution.resp;
    
    import com.yw.module.core.InputOutcomeData.SystemAbilityInputNodeData;
    import lombok.Data;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @Author zl
     * @Description
     * @Date 2021/10/15 9:16
     */
    @Data
    public class AbilityNode {
    
        protected String id;
    
        protected String parentId;
    
        protected String name;
    
        protected List<AbilityNode> children = new ArrayList<>();
    
    
        protected int rank = 0;
    
    
        private Double weight;
    
    
        private List<AbilityQuotaResp> abilityQuotaRespList;
    
        @Data
        public static class AbilityQuotaResp{
            private String id;
    
            private String name;
        }
    }
    心有所想,必有回响
  • 相关阅读:
    【转载】浮点数在内存中的存储格式
    流媒体完全手册
    Windows Mobile 5.0 SDK 下载地址
    实时传输协议 RTP
    JDK环境变量配置
    扩展Windows Mobile模拟器存储空间的方法
    WinSock学习笔记
    实时传输协议 RTCP
    NHibernate从入门到精通系列(4)——持久对象的生命周期(上)
    实时流协议 RTSP
  • 原文地址:https://www.cnblogs.com/zhulei2/p/15410356.html
Copyright © 2020-2023  润新知