对无序分级菜单集合进行重新排序
说明
开发过程中常常遇见对分级集合进行重新排序,如省市县级联结构,分级机构,导航菜单等。本文以省市县级联结构为例进行说明。用Java语言进行描述,JS或者python等开发语言原理类似,可以借鉴。
问题描述
对于一个List集合,存放着如下数据:
"中国人民共和国" "北京市" "河北省" "山西省" "石家庄市" "保定市" "承德市" "太原市" "大同市" "东城区" "西城区" "昌平区" "丰台区" "承德县" "丰宁县"
需要整理成如下格式的List集合:
中华人民共和国
北京市
东城区
西城区
昌平区
丰台区
河北省
石家庄市
保定市
唐山市
迁西县
乐亭县
山西省
......
......
解决方案
1. 定义一个节点类
注意:为了便于描述,省略了getter,setter方法,如果完全引用我所写的代码,请自行添加。
public class TreeNode{
private int id;//编号
private int parentId;//父节点编号
private int level;// 级别
private String name;// 省份/城市名称
public TreeNode(){
}
public TreeNode(int id, int parentId, int level, String name){
this.id = id;
this.parentId = parentId;
this.level = level;
this.name = name;
}
}
2. 排序算法(核心逻辑)
//通过递归,重新排序
/**
* @param parentId 父节点编号
* @param treeNodesList 原始集合
* @param resultList 排序后的集合
*/
private static List<TreeNode> sort(int parentId, List<TreeNode> treeNodesList, List<TreeNode> resultList){
for (TreeNode treeNodes:treeNodesList) {
if (treeNodes.getParentId() == parentId) {
String name = "";
for (int i = 0; i < treeNodes.getLevel(); i++) {
name += "-------------------------------";//为了显示效果,这里直接用-----代替,HTML中可以使用@nbsp;
}
treeNodes.setName(name + treeNodes.getName());
resultList.add(treeNodes);
//如果有子节点,递归
if (hasChild(treeNodesList, treeNodes.getId())){
sort(treeNodes.getId(), treeNodesList, resultList);
}
}
}
return null;
}
//查询是否含有子节点
/**
* @param treeNodesList 原始集合
* @param currentId 当前节点编号
*/
private static boolean hasChild(List<TreeNode> treeNodesList, int currentId){
for (TreeNode treeNodes:treeNodesList) {
if (treeNodes.getParentId() == currentId){
return true;
}
}
return false;
}
3. 初始化数据(你的数据可以来自数据库 或 者其他数据源,本文采用模拟数据)
private static List<TreeNode> initData(){
//编号id 从0开始,0,1,2,3.......
//根节点parentId为-1,level为0.
List<TreeNode> TreeNodes = new ArrayList<>();
TreeNodes.add(new TreeNode(0,-1,0, "中国人民共和国"));
TreeNodes.add(new TreeNode(1, 0, 1,"北京市"));
TreeNodes.add(new TreeNode(2, 0, 1,"河北省"));
TreeNodes.add(new TreeNode(3, 0, 1, "山西省"));
TreeNodes.add(new TreeNode(4, 2, 2, "石家庄市"));
TreeNodes.add(new TreeNode(5, 2, 2, "保定市"));
TreeNodes.add(new TreeNode(6, 2, 2, "承德市"));
TreeNodes.add(new TreeNode(7, 3, 2, "太原市"));
TreeNodes.add(new TreeNode(8, 3, 2, "大同市"));
TreeNodes.add(new TreeNode(9, 1, 2, "东城区"));
TreeNodes.add(new TreeNode(10, 1, 2, "西城区"));
TreeNodes.add(new TreeNode(11, 1, 2, "昌平区"));
TreeNodes.add(new TreeNode(12, 1, 2, "丰台区"));
TreeNodes.add(new TreeNode(13, 6, 3, "承德县"));
TreeNodes.add(new TreeNode(14, 6, 3, "丰宁县"));
return TreeNodes;
}
4. 整体调用测试
public static void main(String[] args) {
List<TreeNode> resultList = new ArrayList<>();
//从根节点开始递归,所以这里为-1,-1是根节点的parentId.
sort(-1, initData(), resultList);
System.out.println(JSONObject.toJSONString(resultList));
}