递归、嵌套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类的代码
import java.util.ArrayList;
import java.util.List; public class Permission { private Integer id;
private String name;
private String url;
private Integer pid;
private boolean open = true;
private boolean checked = false;
private String icon;
private List<Permission> children = new ArrayList<Permission>(); public boolean isChecked() {
return checked;
}
public void setChecked(boolean checked) {
this.checked = checked;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Integer getPid() {
return pid;
}
public void setPid(Integer pid) {
this.pid = pid;
}
public boolean isOpen() {
return open;
}
public void setOpen(boolean open) {
this.open = open;
}
public List<Permission> getChildren() {
return children;
}
public void setChildren(List<Permission> children) {
this.children = children;
} }
使用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层
/**
* 异步加载树结点
* @return
*/
@RequestMapping("/loadData")
@ResponseBody
public List<Permission> loadData(){
List<Permission> permissions=new ArrayList<Permission>();
// 查询所有的许可数据
List<Permission> ps = permissionService.queryAll();
for ( Permission p : ps ) {
// 子节点
Permission child = p;
if ( p.getPid() == 0 ) {
permissions.add(p);
} else {
for ( Permission innerPermission : ps ) {
if ( child.getPid().equals(innerPermission.getId()) ) {
// 父节点
Permission parent = innerPermission;
// 组合父子节点的关系
parent.getChildren().add(child);
break;
}
}
}
} return permissions;
}
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集合就使用了索引,加快查询速度。
递归、嵌套for循环、map集合方式实现树形结构菜单列表查询的更多相关文章
- js前台取用后台传递过来的map集合方式
在处理有些特殊需求的时候,我们需要在前台页面的js中获取后台传递过来的map集合类型的参数,并且进行调用,代码如下: 在后台我们拼装出如下的集合: Map<String,Grade> gr ...
- mybatis框架,使用foreach实现复杂结果的查询--循环List集合方式
需求,根据用户角色列表 查询用户列表信息 之前我们传入的参数是Array,一个数组的形式,现在我们传入的是一个List集合,其他条件没有变化. /** * 需求:传入指定的用户角色,用户角色有1-n ...
- Day11_55_在Map集合中使用泛型
在Map集合中使用泛型 ``` import java.util.HashMap; import java.util.Iterator; import java.util.Map; import ja ...
- Map集合遍历的四种方式理解和简单使用-----不能for循环遍历
Map集合遍历的四种方式理解和简单使用 ~Map集合是键值对形式存储值的,所以遍历Map集合无非就是获取键和值,根据实际需求,进行获取键和值 1:无非就是通过map.keySet()获取到值,然后 ...
- Map集合循环遍历的几种方式
package cn.jdbc.test;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import ...
- Map集合的两种遍历方式
Map集合:即 接口Map<K,V> map集合的两种取出方式: 1.Set<k> keyset: 将map中所有的键存入到set集合(即将所有的key值存入到set中) ...
- 遍历Map集合:java.util.Map.Entry、KeySet两种方式
遍历Map集合的两种方式: 1.用KeySet Map.keySet(),返回一个存放所有key的set集合,通过遍历集合,根据key值取出所有的value值. Map<String,Strin ...
- Map集合遍历的四种方式理解和简单使用
~Map集合是键值对形式存储值的,所以遍历Map集合无非就是获取键和值,根据实际需求,进行获取键和值 1:无非就是通过map.keySet()获取到值,然后根据键获取到值 for(String s:m ...
- Map集合的两种取出方式
Map集合有两种取出方式, 1.keySet:将Map中的键存入Set集合,利用set的迭代器来处理所有的键 举例代码如下: import java.util.*; class Test { publ ...
随机推荐
- Nginx系列二:(Nginx Rewrite 规则、Nginx 防盗链、Nginx 动静分离、Nginx+keepalived 实现高可用)
一.Nginx Rewrite 规则 1. Nginx rewrite规则 Rewrite规则含义就是某个URL重写成特定的URL(类似于Redirect),从某种意义上说为了美观或者对搜索引擎友好, ...
- Git详解之一 Git实战
Git详解之一 Git实战 入门 本章介绍开始使用 Git 前的相关知识.我们会先了解一些版本控制工具的历史背景,然后试着让 Git 在你的系统上跑起来,直到最后配置好,可以正常开始开发工作.读完本章 ...
- gitlab的rack-attack机制和如何设置白名单的记录
目标gitlab是使用源码安装的10.5中文版 大纲: gitlab rack-attack 机制的作用 如何启用和禁用gitlab的rack-attack机制,以及如何配置白名单 如果一个ip被错误 ...
- celery 原理理解
这里有一篇写的不错的:http://www.jianshu.com/p/1840035cb510 自己的“格式化”后的内容备忘下: 我们总在说c10k的问题, 也做了不少优化, 然后优化总是不够的. ...
- 微信小程序获取到Openid
前台代码片段 onLoad: function () { wx.login({ success(res) { console.log('code: '+res.code) if (res.code) ...
- Diagnostics: File file:/tmp/spark-***/__spark_libs__***.zip does not exist
Diagnostics: File file:/tmp/spark-c03df206-c90e-4c97-a2d6-a5d3fdb17811/__spark_libs__303213348409500 ...
- CodeForces - 748E (枚举+脑洞)
E. Santa Claus and Tangerines time limit per test 2 seconds memory limit per test 256 megabytes inpu ...
- Ansible自动化运维之介绍安装与简单使用
参考:http://blog.51cto.com/191226139/2066936 Ansible是什么 Ansible 简单的说是一个配置管理系统(configuration management ...
- asp.net Ajax调用Aspx后台方法
Ajax调用的前提(以aspx文件为例:) 1.首先需要在aspx文件后台中引用using System.Web.Services; 2.需要调用的方法必须是公共的(public).静态的(stati ...
- webuploader 跨域上传demo(还没有写记录一下)
webuploader 跨域上传demo(还没有写记录一下)