如何构建机构,部门树

 

职场萌新最近又碰到头疼的需求,需要把机构数据构造成树型结构传给前端。当时想的是第一次把所有顶级机构传给前端,前端每次展开机构的时候,把当前机构id传给我,我直接找出它的下级机构给前端。因为有了解过一些前端的知识,觉得每次发异步请求,页面理论应该是能够实现的。可是前端小姐姐能力有限,说今天要是不给树结构就找其他小哥哥去联调了,那咱肯定不同意是吧,只能亲自操刀构建树型结构数据。

这里考虑到有的兄弟可能在工作没时间具体看,先上干货吧。

方法一:JDK8流式运算

创建前端所需的dto,其中id、pid、child是必不可少的,其他字段根据实际需求添加。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class NodeOrg {
    /**
     * ID
     */
    private Integer id;

    /**
     * 机构名称
     */
    private String nodeName;

    /**
     * 上级机构ID
     */
    private Integer pid;

    /**
     * 创建时间
     */
    private Date creationDate;

    private List<NodeOrg> child ;

}

 可以像我一样把查出来的所有机构数据用此工具类过滤,也可以直接把下面四步直接写到构建树的服务方法里。

public class TreeUtil {

    public static List<NodeOrg> buildTree(List<NodeOrg> nodes) {

        //先选出非顶级的节点
        List<NodeOrg> list = nodes.stream().filter(node -> node.getPid() != null).collect(Collectors.toList());

        //将这些非顶级节点的数据按pid进行分组
        Map<Integer, List<NodeOrg>> sub = list.stream().collect(Collectors.groupingBy(node -> node.getPid()));

        //循环设置对应的子节点(根据id = pid)
        nodes.forEach(node -> node.setChild(sub.get(node.getId())));

        //选出父节点数据
        List<NodeOrg> collect = nodes.stream().filter(node -> node.getPid() == null).collect(Collectors.toList());
        return collect;
    }
}

 造一些假数据试一试有没有问题。

25f30bac7f3a4c999d7d50ad0b910c01.png

 然后swagger测试一下成果吧。

[
  {
    "id": 1,
    "nodeName": "西瓜科技",
    "pid": null,
    "creationDate": "2021-02-24T02:23:50.000+0000",
    "child": [
      {
        "id": 2,
        "nodeName": "一级部门-01",
        "pid": 1,
        "creationDate": "2022-08-11T16:43:17.000+0000",
        "child": [
          {
            "id": 6,
            "nodeName": "二级部门-01-A1",
            "pid": 2,
            "creationDate": "2022-08-11T16:43:21.000+0000",
            "child": [
              {
                "id": 8,
                "nodeName": "三级部门-01-A1-A1",
                "pid": 6,
                "creationDate": "2022-08-11T16:43:23.000+0000",
                "child": null
              }
            ]
          },
          {
            "id": 7,
            "nodeName": "二级部门-01-B1",
            "pid": 2,
            "creationDate": "2022-08-11T16:43:22.000+0000",
            "child": null
          }
        ]
      },
      {
        "id": 3,
        "nodeName": "一级部门-02",
        "pid": 1,
        "creationDate": "2022-08-11T16:43:19.000+0000",
        "child": [
          {
            "id": 9,
            "nodeName": "二级部门-02-A2",
            "pid": 3,
            "creationDate": "2022-08-11T16:43:24.000+0000",
            "child": null
          }
        ]
      },
      {
        "id": 4,
        "nodeName": "一级部门-03",
        "pid": 1,
        "creationDate": "2022-08-11T16:43:20.000+0000",
        "child": [
          {
            "id": 10,
            "nodeName": "二级部门-03-B3",
            "pid": 4,
            "creationDate": "2022-08-11T16:43:24.000+0000",
            "child": null
          }
        ]
      },
      {
        "id": 5,
        "nodeName": "一级部门-04",
        "pid": 1,
        "creationDate": "2022-08-11T16:43:20.000+0000",
        "child": null
      }
    ]
  }
]

搞定下班!

方法二:逐步理解,硬撸法

正所谓,授人与鱼,不如授人与渔。有时间的兄弟可以跟我一起学学捕鱼技巧。

其实,构造树型结构就四部,把理念掌握了,实现起来就会有方向。

一、去除顶级节点


34c8003d2c584c63a7368594ed148f01.png


//获取非子结点
    static List<NodeOrg> getChildTree(List<NodeOrg> node) {
        List childList = new ArrayList<>();
        for (NodeOrg nodeOrg : node) {
            if (nodeOrg.getPid() != null) {
                childList.add(nodeOrg);
            }
        }
        return childList;
    }

二、将所有子节点按父节点分组


1b16f7c265604034ae34c301aa861efe.png


//将父节点相同的分组
    static Map<Integer, List<NodeOrg>> groupTree(List<NodeOrg> childList) {
        Map<Integer, List<NodeOrg>> map = new HashMap<>();
        for (NodeOrg nodeOrg : childList) {
            List<NodeOrg> parallelNodeList;
            Integer pid = nodeOrg.getPid();
            if (map.containsKey(pid)) {
                parallelNodeList = map.get(pid);
            } else {
                parallelNodeList = new ArrayList<>();
            }
            parallelNodeList.add(nodeOrg);
            map.put(pid, parallelNodeList);
        }
        return map;
    }

三、按分组分别注入到对应的父节点中去。


056777dc263c4689841f354f09da99c3.png

 


//注入子节点
    static void setChildNode(Map<Integer, List<NodeOrg>> groupTree, List<NodeOrg> node) {
        Set<Map.Entry<Integer, List<NodeOrg>>> entries = groupTree.entrySet();
        for (NodeOrg nodeOrg : node) {
            for (Map.Entry<Integer, List<NodeOrg>> entry : entries) {
                Integer id = nodeOrg.getId();
                Integer key = entry.getKey();
                List<NodeOrg> value = entry.getValue();
                if (id==key) {
                    nodeOrg.setChild(value);
                }
            }
        }

    }

四、过滤出父节点。

//获取顶级节点数据
    static List<NodeOrg> getTopTree(List<NodeOrg> node) {
        List<NodeOrg> treeList = new ArrayList<>();
        for (NodeOrg nodeOrg : node) {
            if (nodeOrg.getPid() != null) {
                continue;
            }
            treeList.add(nodeOrg);
        }
        return treeList;
    }

最后测试一下有没有用。

[
  {
    "id": 1,
    "nodeName": "西瓜科技",
    "pid": null,
    "creationDate": "2021-02-24T02:23:50.000+0000",
    "child": [
      {
        "id": 2,
        "nodeName": "一级部门-01",
        "pid": 1,
        "creationDate": "2022-08-11T16:43:17.000+0000",
        "child": [
          {
            "id": 6,
            "nodeName": "二级部门-01-A1",
            "pid": 2,
            "creationDate": "2022-08-11T16:43:21.000+0000",
            "child": [
              {
                "id": 8,
                "nodeName": "三级部门-01-A1-A1",
                "pid": 6,
                "creationDate": "2022-08-11T16:43:23.000+0000",
                "child": null
              }
            ]
          },
          {
            "id": 7,
            "nodeName": "二级部门-01-B1",
            "pid": 2,
            "creationDate": "2022-08-11T16:43:22.000+0000",
            "child": null
          }
        ]
      },
      {
        "id": 3,
        "nodeName": "一级部门-02",
        "pid": 1,
        "creationDate": "2022-08-11T16:43:19.000+0000",
        "child": [
          {
            "id": 9,
            "nodeName": "二级部门-02-A2",
            "pid": 3,
            "creationDate": "2022-08-11T16:43:24.000+0000",
            "child": null
          }
        ]
      },
      {
        "id": 4,
        "nodeName": "一级部门-03",
        "pid": 1,
        "creationDate": "2022-08-11T16:43:20.000+0000",
        "child": [
          {
            "id": 10,
            "nodeName": "二级部门-03-B3",
            "pid": 4,
            "creationDate": "2022-08-11T16:43:24.000+0000",
            "child": null
          }
        ]
      },
      {
        "id": 5,
        "nodeName": "一级部门-04",
        "pid": 1,
        "creationDate": "2022-08-11T16:43:20.000+0000",
        "child": null
      }
    ]
  }
]

效果和流式的一模一样!创作不易,点个赞支持一下吧:)

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

抑制疯狂的刀鞘

编写不易,你的鼓励就是我最大动

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值