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