当前位置: 首页 > 知识库问答 >
问题:

java - 树结构递归如何优化?

陈知
2023-04-21

翻到祖师爷代码,发现树结构的数据是后端通过递归去生成的,效率非常低,请问有什么方法可以优化吗?

public List<Map> createGroupTreeNode() {
    List<Map> childrenList = new ArrayList<Map>();
    getChildList(0L,childrenList);
    List<Map> treeList = new ArrayList<Map>();
    Map map = new HashMap();
    map.put("id", 0);
    map.put("text","根节点");
    map.put("isleaf", "0");
    map.put("icon", "fa fa-folder");
    Map subMap = new HashMap();
    subMap.put("opened", true);
    subMap.put("selected", true);
    map.put("state", subMap);
    map.put("children", childrenList);
    treeList.add(map);
    return treeList;  
}
public List<Map> getChildList(Long id,List<Map> childrenList){
    List<BaseGroup> childList = baseMapper.childListByParentId(id);
    if(childList != null && childList.size() > 0){
        List<Map> tempMap = new ArrayList<Map>();
        for(int i = 0; i < childList.size(); i++){
            List<Map> mylist = getChildList(childList.get(i).getId(),childrenList);
            Map map = new HashMap();
            if(mylist == null){
                map.put("id", childList.get(i).getId());
                map.put("text", childList.get(i).getNumber() + " - " + childList.get(i).getName());
                map.put("isleaf", "1");
                map.put("icon", "fa fa-folder");
                Map subMap = new HashMap();
                subMap.put("opened", false);
                map.put("state", subMap);
                tempMap.add(map);
            }else{
                map.put("id", childList.get(i).getId());
                map.put("text", childList.get(i).getNumber() + " - " + childList.get(i).getName());
                map.put("isleaf", "0");
                map.put("icon", "fa fa-folder");
                map.put("children", mylist);
                Map subMap = new HashMap();
                subMap.put("opened", false);
                map.put("state", subMap);
                tempMap.add(map);
            }
            if(id == 0){
                childrenList.add(map);
            }
        }
        return tempMap;
    }
    return null;
}

共有4个答案

孟成化
2023-04-21

没看出哪里效率低
只是觉得这人应该去写php

颛孙和颂
2023-04-21

如果 baseMapper 是数据库查询的话的确性能会很差,但跟递归没关系。
可以一次性查询出数据库记录,在内存中递归组合。如果数据库记录较多,可以加path字段辅助查询收缩范围。

刘运浩
2023-04-21

树状结构正确的处理方式是:使用缓存。

详细来说,初次使用的时候,用各种方法将树状结构生成出来,存为JSON格式的字符串。

后续直接读取这个JSON在前端渲染。

有人会说,如果数据更新了,那么这个缓存的就不能反映真实状况了。

所以,我们会先识别出影响树状结构源数据的所有入口,然后在入口触发这个JSON的更新。这样,就可以让JSON的更新不在每次访问的时候触发,可以减少频繁刷新导致的性能崩溃。

汝跃
2023-04-21

getChildListchildrenList 看起来是个输出参数,这里只有在 id == 0L 的时候会把元素加到 childrenList 中去。所以这个输入参数只在 id == 0L 的时候会使用。既然 getChildList 会把找到的列表返回出去,那完全不需要这个输出参数,在 createGroupTreeNode 里直接使用它的返回值就好。

public List<Map> createGroupTreeNode() {
    List<Map> childrenList = getChildList(0L);
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 不用初始化并作为输入参数传入,直接使用返回值就行
    // ....
}

public List<Map> getChildList(Long id) {
//                                   ^^^ 去掉 childrenList 参数
    
    // ...
    // if(id == 0){
    //     childrenList.add(map);
    // }
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 不需要了
}

总体来说,关于递归,就只有这一点问题。

然后在里面,for 循环中的循环变量 i 只有一个作用,就是 childList.get(i),频繁的去使用 childList.get(i) 肯定不如缓存一个变量效率高,所以可以改为

for (int i = 0; i < childList.size(); i++) {
    BaseGroup it = childList.get(i);
    // 下面都用 it 代替 childList.get(i)
}

或者直接用增强 for 循环

 for (BaseGroup it : childList) {
     // ...
 }

另外在 for 循环中的 if 分支,比较一下发现只有一丁点区别,就是在处理 isleafchildren 的时候,所以可以把其他 .put 都提取出来,只处理有差异的部分

Map map = new HashMap();
map.put("id", it.getId());
// ...

List<Map> mylist = getChildList(it.getId());
// ^^^ 这句话后移到使用它的地方,不需要提前去取
//                 ^^^^^^^^^^^^^^^^^^^^^^^^ 没要第二个参数了,前面说过
if (mylist == null) {
    map.put("isleaf", "1");
}
else {
    map.put("isleaf", "0");
    map.put("children", mylist);
}
 类似资料:
  • 问题内容: 我有一个将位置链接在一起的数据库表;一个位置可以在一个位置,也可以在另一个位置内。 这是深入探讨MySQL / PHP的深度: 在给定父级位置的情况下,如何使用MySQL如何获得其所有后代位置,无论深度如何? 问题答案: mysql.com上有 一篇漂亮的文章 ,概述了管理分层数据的各种方法。我认为它为您的问题提供了完整的解决方案,并显示了各种不太简单但较快的方法(例如嵌套集)。

  • 一、想要实现的效果 二、我的代码 public class People { } public static void main(String[] args) { 三、代码执行结果 四、解释 我递归用的少,用起来有点不达意。上面自己写的递归方法虽然能实现递归效果,但问题很大。 4.1、我的方法返回的只是命中项,而不是一个树的结构(除非第一层就命中了)。 4.2、返回的树里没有剔除未命中项。 上述两

  • 本文向大家介绍数据结构 二叉树的递归与非递归,包括了数据结构 二叉树的递归与非递归的使用技巧和注意事项,需要的朋友参考一下 数据结构 二叉树的递归与非递归 实例代码:  先序遍历(递归法)   后序遍历      感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

  • 问题内容: 我的内存中有一个树结构,我想使用Django模板以HTML呈现。 将有一些对象是,并且是的列表。将在模板的内容中传递。 我发现这个的如何可能实现一个讨论,但海报表明,这在生产环境中可能不是很好。 有人知道更好的方法吗? 问题答案: 使用with模板标记,我可以做树/递归列表。 样例代码: 主模板:假设是树的一个或多个根的列表 tree_view_template.html呈现neste

  • 我现在正在实现模拟N体问题的Barnes-Hut算法。我只想问关于建筑树的部分。 我做了两个函数来为它构建树。 我递归地构建树,并在构建时打印每个节点的数据,一切看起来都是正确的,但当程序返回到主函数时,只有树的根和根的子节点存储值。其他节点的值没有被存储,这很奇怪,因为我在递归过程中打印了它们,它们应该被存储。 这是经过修改的代码的一部分,我认为问题可能在哪里: 下面是函数set_root_an

  • 我一直在用这个四叉树http://www.astroml.org/book_figures/chapter2/fig_quadtree_example.html 在一些数据上。但是我现在需要结果结构的嵌套表示。 其结构类似于: 这里的子元素是递归元素,它是一个列表,包括进一步的实例。最低深度没有子级(为0),是我想要访问的表示。因此,在这种情况下,我会访问数据 最终,我希望在最低级别的数据表示像: