递归、嵌套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集合就使用了索引,加快查询速度。

原文地址:https://www.cnblogs.com/limn/p/9515248.html

时间: 2024-07-30 20:01:08

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

mybatis框架,使用foreach实现复杂结果的查询--循环List集合方式

需求,根据用户角色列表  查询用户列表信息 之前我们传入的参数是Array,一个数组的形式,现在我们传入的是一个List集合,其他条件没有变化. /** * 需求:传入指定的用户角色,用户角色有1-n,获取这些用户角色下的用户列表信息 * @param roleids * @return */ public List<User> getUserListByRoleid_List(List<Integer> roleList); <resultMap type="Us

Java循环map集合

1 Map<Integer,String> map = new LinkedHashMap<Integer,String>(); 2 map.put(1, "星期一"); 3 map.put(2, "星期二"); 4 map.put(3, "星期三"); 5 map.put(4, "星期四"); 6 map.put(5, "星期五"); 7 map.put(6, "星期六&

Map集合的遍历

Map是将键映射到值的对象.一个映射不能包含重复的键:每个键最多只能映射到一个值.当发生重复添加的话,后面的值将前面的覆盖,适用于put()和putAll()两个方法. Map集合常用的两种遍历方式: 1.通过Key来查找对应的Value 2.通过键值对的Set集合来遍历Map集合 public class Person { //姓名 private String name; //年龄 private int age; //无参构造 public Person() { } //有参构造 publ

Map集合遍历的四种方式理解和简单使用-----不能for循环遍历

~Map集合是键值对形式存储值的,所以遍历Map集合无非就是获取键和值,根据实际需求,进行获取键和值 1:无非就是通过map.keySet()获取到值,然后根据键获取到值 for(String s:map.keySet()){            System.out.println("key : "+s+" value : "+map.get(s));     } 2:通过Map.Entry(String,String) 获取,然后使用entry.getKey(

Map集合的两种遍历方式

Map集合:即 接口Map<K,V> map集合的两种取出方式:    1.Set<k> keyset: 将map中所有的键存入到set集合(即将所有的key值存入到set中), 因为Set具备迭代器,可以进行迭代遍历. 所有可以迭代方式取出所有的链,再根据get方法.获取每一个键对应的值. Map 集合的取出原理: 将map集合转成set集合. 再通过迭代器取出    2. set<Map.Entry<k,v>>  entrySet: 将map集合中的映射

Map集合的两种取出方式

Map集合有两种取出方式, 1.keySet:将Map中的键存入Set集合,利用set的迭代器来处理所有的键 举例代码如下: import java.util.*; class Test { public static void main(String[] args) { Map<String, Integer> map = new HashMap<String, Integer>(); map.put("fan", 23); map.put("pen

查询字符串中字母的个数(两种实现方式1,list与set集合 2,map集合)

题目: 取出一个字符串中字母出现的次数.如:字符串:"abcde%^kka27qoq" ,输出格式为:a(2)b(1)k(2)... 第一种方式(set和list结合使用): package itheima; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; /** * .取出一个字符串中字母出现的次数.如:字符串:"

25.使用Iterator和增强型for循环遍历Map集合

/** * 宠物类,狗狗和企鹅的父类. */ public abstract class Pet { protected String name = "无名氏";// 昵称 protected int health = 100;// 健康值 protected int love = 0;// 亲密度 public abstract void eat(); //抽象方法eat(),负责宠物吃饭功能. /** * 无参构造方法. */ public Pet() { } /** * 有参构造

【剑指offer】递归循环两种方式反转链表

转载请注明出处:http://blog.csdn.net/ns_code/article/details/25737023 本文分别用非递归和递归两种方式实现了链表的反转,在九度OJ上AC. 题目描述: 输入一个链表,反转链表后,输出链表的所有元素.(hint : 请务必使用链表) 输入: 输入可能包含多个测试样例,输入以EOF结束.对于每个测试案例,输入的第一行为一个整数n(0<=n<=1000):代表将要输入的链表的个数.输入的第二行包含n个整数t(0<=t<=1000000)