通过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.利用队列先进先出的特点,实现对同级别元素的访问。
如果大家有碰到类似的业务场景希望可帮助到大家。

Guess you like

Origin blog.csdn.net/weixin_48470176/article/details/117605561