在实际代码开发中,构造一棵树是一个比较常见的业务场景,实现方式有多种多样,但是如何以一种较为优雅的方式构造一棵树,却是一个值得深思的问题。
下面的方法,整体思路是:
1)首先查出所有的节点,这样与数据库只交互一次,减少IO;
2)第二次采用递归的方式构建树;
3)采用 stream表达式,注意排序的两种实现方式; 代码如下:
1 public List<CategoryEntity> queryTree() { 2 3 //1. 首先获取所有的实体类 4 List<CategoryEntity> categoryEntities = baseMapper.selectList(null); 5 6 //2. 组装树形结构 7 // 特点: 8 // 1) 首先查出所有的节点,与数据库只交互一次,减少IO 9 // 2) 然后对查询的节点采用递归的方式进行构造树 10 List<CategoryEntity> firstMenu = categoryEntities.stream().filter((categoryEntity) -> { 11 return categoryEntity.getParentCid() == 0; 12 }).map((menu) -> { 13 menu.setChildren(getAllChildrenTree(menu, categoryEntities)); 14 return menu; 15 // 采用这种方式排序,注意非空判断 16 }).sorted((menu1, menu2) -> { 17 return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort()); 18 }).collect(Collectors.toList()); 19 20 21 return categoryEntities; 22 } 23 24 25 //递归获取所有的子节点 26 private List<CategoryEntity> getAllChildrenTree(CategoryEntity root, List<CategoryEntity> all) { 27 List<CategoryEntity> tree = all.stream().filter((categoryEntity) -> { 28 return categoryEntity.getParentCid() == root.getCatId(); 29 }).map((categoryEntity) -> { 30 // 递归获取 所有的子菜单 31 categoryEntity.setChildren(getAllChildrenTree(categoryEntity, all)); 32 return categoryEntity; 33 //一级菜单正序排列,其他的逆序排列 34 //采用两种排序方式进行实现,采用这种方式排序,注意非空判断 Comparator.nullsFirst(Integer::compareTo) 35 }).sorted(Comparator.comparing(CategoryEntity::getSort, Comparator.nullsFirst(Integer::compareTo)).reversed()) 36 .collect(Collectors.toList()); 37 return tree; 38 }