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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM