通过parentId父节点对树形结构数据排序,类似部门层级排序,同级别遍历,附java实现代码

背景

现有公司部门数据,通过parentId进行存储,类似与树形结构,现有业务单据中的某个属性,匹配到部门中有该属性的部门内的员工处理,但由于部门中该属性可能重复,按照业务要求,需要等级高的部门优先处理,所以涉及到对部门进行排序。该文章仅为自己记录,各位如果有类似的需求也可以参考。

基础数据

部门图

在这里插入图片描述

部门图如上所示,红色为一级部门,一级部门有3个(其实也可以只建一个公司,这样就是一棵完整的树,现在我们不这样做,难度会稍稍大),黄色是二级部门,绿色是三级部门,蓝色是四级部门。

需求

如背景介绍,我们需要按照部门层级关系进行排序。同一级别的顺序可以无序,即要求的顺序是:红色(A)>黄色(B)>绿色(C)>蓝色(D),同一个色系顺序忽略。

代码实现

1.先建立部门对象

public class Position {

    /** 岗位ID */
    private Long id;

    /** 岗位名字 */
    private String name;

    /** 岗位 code */
    private String code;

	/** 父岗位code*/
    private String parentCode;

    public Position() {
    }

    public Position(Long id, String code, String name, String parentCode) {
        this.id = id;
        this.name = name;
        this.code = code;
        this.parentCode = parentCode;
    }
	// getting/setting方法
}

2.模拟基础数据

实际的数据是存在数据库的,数据库中也只是通过parentid进行关联,这里我们模拟下数据库的数据采用parentcode关联排序,

public class Test {
	private static List<Position> originList = new ArrayList<>();

    static {
        originList.add(new Position(1L,"A1","市场部",null));
        originList.add(new Position(2L,"A2","总经办",null));
        originList.add(new Position(3L,"A3","党支部",null));
        originList.add(new Position(4L,"B1","市场拓展部","A1"));
        originList.add(new Position(5L,"B2","华南分部","A1"));
        originList.add(new Position(9L,"B3","华北分部","A1"));
        originList.add(new Position(10L,"B4","总经办-核查小组","A2"));
        originList.add(new Position(6L,"C1","华南分部-广东部","B2"));
        originList.add(new Position(7L,"C2","华南分部-广西部","B2"));
        originList.add(new Position(8L,"C3","华南分部-海南部","B2"));
        originList.add(new Position(11L,"C4","华北分部-北京分部","B3"));
        originList.add(new Position(12L,"C5","华北分部-天津分部","B3"));
        originList.add(new Position(13L,"D1","华北分部-天津分部-天津海河分销部","C5"));
        originList.add(new Position(14L,"D2","华北分部-天津分部-天津滨海分销部","C5"));
    }
}

3.打乱顺序

上面的添加的数据其实是有顺序的,为了模拟无序的数据我们采用java自带的api将数据打乱。

		//洗牌算法,有兴趣可以研究下
        Collections.shuffle(originList);

4.排序(编辑,访问)

	public static List<Position> sort(List<Position> originList){

        
        //先找出所有的root元素,即父级部门
        List<Position> rootList = originList.stream()
                .filter(l -> l.getParentCode() == null).collect(Collectors.toList());
        Queue<Position> queues = new LinkedList<>(rootList);

        return findChildren(originList, queues);
    }

    private static List<Position> findChildren(List<Position> originList,Queue<Position> queues){
        List<Position> childrenList = new ArrayList<>();

        while (queues.size() > 0){
            Position poll = queues.poll(); //弹出队列
            childrenList.add(poll);
            for (Position position : originList) {
                if(Objects.equals(position.getParentCode(),poll.getCode())){
                    queues.offer(position); //加入队列
                }

            }
        }

        return childrenList;


    }

6.测试

    //使用main方法测试
	public static void main(String[] args) {
        List<String> originSort = originList.stream().map(Position::getCode).collect(Collectors.toList());
        System.out.println("原始顺序(目标顺序):"+originSort);

        Collections.shuffle(originList);
        System.out.println("乱序:"+originList.stream().map(Position::getCode).collect(Collectors.toList()));

        List<Position> listSort = sort(originList);
        System.out.println("排序后:"+listSort.stream().map(Position::getCode).collect(Collectors.toList()));

    }

执行结果如下:

原始顺序(目标顺序)[A1, A2, A3, B1, B2, B3, B4, C1, C2, C3, C4, C5, D1, D2]
乱序:[A1, B2, B1, C3, C1, C4, A2, C2, D1, A3, C5, D2, B4, B3]
排序后:[A1, A2, A3, B2, B1, B3, B4, C3, C1, C2, C4, C5, D1, D2]

总接

此排序(遍历访问)的关键步骤有两部,
1.找出所有的一级元素,即跟节点。
2.利用队列先进先出的特点,实现对同级别元素的访问。
如果大家有碰到类似的业务场景希望可帮助到大家。

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
假设你有一个部门集合 `List<Department>`,其中每个部门对象有如下属性: ```csharp public class Department { public int Id { get; set; } public string Name { get; set; } public int ParentId { get; set; } public int Level { get; set; } public bool IsLeaf { get; set; } public bool Expanded { get; set; } } ``` 其中 `Id` 是部门的唯一标识,`Name` 是部门名称,`ParentId` 是父部门的标识,`Level` 是部门所在的层级,`IsLeaf` 表示该部门是否是叶子节点,`Expanded` 表示该节点是否默认展开。 为了符合 jqGrid 树形表格的结构,需要进行如下处理: 1. 对部门集合进行排序,按照 `ParentId` 和 `Id` 排序。这样可以保证父节点在前,子节点在后的顺序。 ```csharp var sortedDepartments = departments.OrderBy(d => d.ParentId).ThenBy(d => d.Id).ToList(); ``` 2. 遍历部门集合,设置每个部门的 `Level`、`IsLeaf` 和 `Expanded` 属性。 ```csharp foreach (var department in sortedDepartments) { int parentId = department.ParentId; if (parentId == 0) { // 根节点 department.Level = 0; department.IsLeaf = false; department.Expanded = true; } else { // 非根节点 var parentDepartment = sortedDepartments.SingleOrDefault(d => d.Id == parentId); if (parentDepartment != null) { department.Level = parentDepartment.Level + 1; department.IsLeaf = true; parentDepartment.IsLeaf = false; parentDepartment.Expanded = true; } } } ``` 上述代码中,首先判断当前部门是否为根节点(即 `ParentId` 为 0),如果是根节点,则将其 `Level` 设为 0,`IsLeaf` 设为 false(因为根节点一定不是叶子节点),`Expanded` 设为 true(因为根节点默认展开)。 如果当前部门不是根节点,则找到其父部门对象,计算当前部门的 `Level`,并将父部门的 `IsLeaf` 设为 false(因为父部门肯定是非叶子节点),`Expanded` 设为 true(因为父部门默认展开)。 最后遍历部门集合后,每个部门对象就都符合 jqGrid 树形表格的结构了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值