1. 前言
继上文java树形结构的递归recursion之后,考虑递归会出现的StackOverflow问题,采用Stack+循环的方式改造;
参考代码:
public static Object[] WalkDirStack2(File file) {
List<Object> list = new ArrayList<>();
Stack<File> stack = new Stack<>();
stack.push(file);
while (!stack.empty()){
File gf = stack.pop();
File[] fileList = gf.listFiles();
assert fileList != null;
for (File f : fileList) {
if (f.isDirectory()) {
list.add(f.getName());
stack.push(f);
}else {
list.add( f.getName());
}
}
}
return list.toArray();
}
参考的这个是根据文件路径,遍历所有目录结构,最后获取当前目录下的所有文件;
而我们这里的需求其实是逆向过程,是所有的项都存在一张表中,都是零散的,去根据id和pid建立起一个树形结构;
代码如下:
/**
* 通过Stack+循环方式构造树
* @param categoryList 分类列表
* @param rootId 父节点
* @return 分类树
*/
@Override
public CategoryTree buildCategoryTreeByForEach(final List<Category> categoryList, final Long rootId){
if (categoryList.isEmpty()) return null;
List<CategoryTree> categoryTrees = new ArrayList<>();
Stack<CategoryTree> stack = null;
CategoryTree ctRoot = null;
for (Category category: categoryList) {
categoryTrees.add(new CategoryTree(category.getId(),category.getPid(),category.getName()));
if(category.getId().equals(rootId)) {
ctRoot = new CategoryTree(category.getId(),category.getPid(),category.getName());
}
}
if(null != ctRoot){
stack = new Stack<>();
stack.push(ctRoot);
}
while (null != stack && !stack.empty()){
CategoryTree pop = stack.pop();
long id = pop.getId();
List<CategoryTree> cts = categoryTrees.stream().filter(item -> id == item.getPid()).collect(Collectors.toList());
pop.setChildren(cts);
if (!cts.isEmpty()){
for (CategoryTree ct: cts) {
long _id = ct.getId();
List<CategoryTree> cats = categoryTrees.stream().filter(item -> _id == item.getPid()).collect(Collectors.toList());
ct.setChildren(cats);
if (cats.isEmpty()){
ct.setLeaf(true);
}else {
ct.setLeaf(false);
stack.push(ct);
}
}
}
}
return ctRoot;
}
相比递归,利用了Stack结构和循环,结合stream()根据pid,快速查找集合中的子节点,最终测试效果一样;
整体上来看更简洁明了,而且不会有StackOverflow问题!