• 递归、嵌套for循环、map集合方式实现树形结构菜单列表查询


    有时候, 我们需要用到菜单列表,但是怎么样去实现一个菜单列表的编写呢,这是一重要的问题。

    比如我们需要编写一个树形结构的菜单,那么我们可以使用JQuery的zTree插件:http://www.treejs.cn/v3/main.php#_zTreeInfo

    例如现在需要编写一个这样的菜单列表。那么就可以使用JQuery的zTree插件。

    先看一下数据库表结构。

    CREATE TABLE `permission` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(255) DEFAULT NULL,
      `pid` int(11) DEFAULT NULL,
      `url` varchar(255) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

    1、前端页面。

                    <div class="panel-body">
    
                        <ul id="permissionTree" class="ztree"></ul>
    
                    </div>
    <script>
       $(function () {
    
           var setting = {
               async: {
                   enable: true,
                   url:"${APP_PATH}/permission/loadData",
                   autoParam:["id", "name=n", "level=lv"],
                   otherParam:{"otherParam":"zTreeAsyncTest"},
               }
    
    
           };
    
            //树形结构
           $.fn.zTree.init($("#permissionTree"), setting);
        });
    </script>

    2、在这里呢,我使用的是ssm框架。所以就提交到controller层来进行操作。

    Permission类的代码

     1 import java.util.ArrayList;
     2 import java.util.List;
     3 
     4 public class Permission {
     5 
     6     private Integer id;
     7     private String name;
     8     private String url;
     9     private Integer pid;
    10     private boolean open = true;
    11     private boolean checked = false;
    12     private String icon;
    13     private List<Permission> children = new ArrayList<Permission>();
    14     
    15     public boolean isChecked() {
    16         return checked;
    17     }
    18     public void setChecked(boolean checked) {
    19         this.checked = checked;
    20     }
    21     public String getIcon() {
    22         return icon;
    23     }
    24     public void setIcon(String icon) {
    25         this.icon = icon;
    26     }
    27     public Integer getId() {
    28         return id;
    29     }
    30     public void setId(Integer id) {
    31         this.id = id;
    32     }
    33     public String getName() {
    34         return name;
    35     }
    36     public void setName(String name) {
    37         this.name = name;
    38     }
    39     public String getUrl() {
    40         return url;
    41     }
    42     public void setUrl(String url) {
    43         this.url = url;
    44     }
    45     public Integer getPid() {
    46         return pid;
    47     }
    48     public void setPid(Integer pid) {
    49         this.pid = pid;
    50     }
    51     public boolean isOpen() {
    52         return open;
    53     }
    54     public void setOpen(boolean open) {
    55         this.open = open;
    56     }
    57     public List<Permission> getChildren() {
    58         return children;
    59     }
    60     public void setChildren(List<Permission> children) {
    61         this.children = children;
    62     }
    63     
    64 }

     使用controller这里我使用三种方式来进行查找 。

      (1)递归方式读取各节点

    controller层

        /**
         * 异步加载树结点
         * @return
         */
        @RequestMapping("/loadData")
        @ResponseBody
        public List<Permission> loadData(){
            // 递归查询数据
        Permission parent = new Permission();
        parent.setId(0);
        queryChildPermissions(parent);
        return parent.getChildren();        
        }
        /**
         * 递归查询许可信息
         * 1) 方法自己调用自己
         * 2)方法一定要存在跳出逻辑
         * 3)方法调用时,参数之间应该有规律
         * 4) 递归算法,效率比较低
         * @param parent
         */
        private  void queryChildPermissions(Permission parent){
            List<Permission> childPermissions = permissionService.queryChildPermissions(parent.getId());
            for (Permission permission :childPermissions) {
                queryChildPermissions(permission);
            }
            parent.setChildren(childPermissions);
        }

     service层

        public Permission queryRootPermission() {
            return permissionMapper.queryRootPermission();
        }

     mappern层

        @Select("select * from permission where pid is null")
        Permission queryRootPermission();

      (2)嵌套for循环方式读取各节点

    controller层

     1     /**
     2      * 异步加载树结点
     3      * @return
     4      */
     5     @RequestMapping("/loadData")
     6     @ResponseBody
     7     public List<Permission> loadData(){
     8         List<Permission> permissions=new ArrayList<Permission>();
     9         // 查询所有的许可数据
    10         List<Permission> ps = permissionService.queryAll();
    11         for ( Permission p : ps ) {
    12             // 子节点
    13             Permission child = p;
    14             if ( p.getPid() == 0 ) {
    15                 permissions.add(p);
    16             } else {
    17                 for ( Permission innerPermission : ps ) {
    18                     if ( child.getPid().equals(innerPermission.getId()) ) {
    19                         // 父节点
    20                         Permission parent = innerPermission;
    21                         // 组合父子节点的关系
    22                         parent.getChildren().add(child);
    23                         break;
    24                     }
    25                 }
    26             }
    27         }
    28 
    29 
    30        return permissions;
    31     }

     service层

        public List<Permission> queryAll() {
            return permissionMapper.queryAll();
        }

    mapper层

        @Select("select * from permission")
        List<Permission> queryAll();

       (3)map集合方式读取各节点

     controller层

        /**
         * 异步加载树结点
         * @return
         */
        @RequestMapping("/loadData")
        @ResponseBody
        public List<Permission> loadData(){
            List<Permission> permissions=new ArrayList<Permission>();
    
            // 查询所有的许可数据
            List<Permission> ps = permissionService.queryAll();
    
            Map<Integer, Permission> permissionMap = new HashMap<Integer, Permission>();
            for (Permission p : ps) {
                permissionMap.put(p.getId(), p);
            }
            for ( Permission p : ps ) {
                Permission child = p;
                if ( child.getPid() == 0 ) {
                    permissions.add(p);
                } else {
                    Permission parent = permissionMap.get(child.getPid());
                    parent.getChildren().add(child);
                }
            }
           return permissions;
        }

    service层

        public List<Permission> queryAll() {
            return permissionMapper.queryAll();
        }

    mapper层

        @Select("select * from permission")
        List<Permission> queryAll();

    三种方法的总结 :

    使用递归会使数据库查询非常频繁,不能进行性能优化

    使用嵌套for循环没有使用索引,不够快速

    使用map集合就使用了索引,加快查询速度。

  • 相关阅读:
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
  • 原文地址:https://www.cnblogs.com/limn/p/9515248.html
Copyright © 2020-2023  润新知