如果少量数据组装树结构可以使用递归或循环都是可以的,但是对于几十 W 的数据量可能就会报栈溢出或者超时。这里使用的是Java 8 的 并发流实现,所使用的数据是省市县五级联动查询。返回属性结构。
核心代码
@Override
public List<SysAreaTreeDto> getTreeList(Long pid) {
long start = System.currentTimeMillis();
//查询所有数据
QueryWrapper<SysAreaEntity> wrapper = Wrappers.query();
List<SysAreaEntity> list = baseMapper.selectList(wrapper);
if(CollectionUtils.isEmpty(list)){
return new ArrayList<>();
}
//将数据转为树形结构的数据
List<SysAreaTreeDto> dtoList = list.parallelStream().map(item->{
SysAreaTreeDto dto = new SysAreaTreeDto();
BeanUtils.copyProperties(item, dto);
return dto;
}).collect(Collectors.toList());
List<SysAreaTreeDto> result = buildTree(dtoList, pid);
System.out.println(System.currentTimeMillis() - start);
return result;
}
/**
* 组装树结构
* @param dtoList 所有数据
* @param pid 父主键
* @return 树形结构
*/
private List<SysAreaTreeDto> buildTree(List<SysAreaTreeDto> dtoList, Long pid) {
//先选出非顶级的节点
List<SysAreaTreeDto> list = dtoList.parallelStream().filter(item -> item.getPid() != pid).collect(Collectors.toList());
//将这些非顶级节点的数据按pid进行分组
Map<Long, List<SysAreaTreeDto>> sub = list.parallelStream().collect(Collectors.groupingBy(SysAreaTreeDto::getPid));
//循环设置对应的子节点(根据id = pid)
dtoList.parallelStream().forEach(node -> node.setChildren(sub.get(node.getId())));
//过滤掉父节点数据
List<SysAreaTreeDto> collect = dtoList.parallelStream().filter(node -> node.getPid() == 0).collect(Collectors.toList());
return collect;
}
省市县五级联动 SQL 下载路径 https://download.csdn.net/download/weixin_45267345/86508057