Java-无限层级菜单结构

业务分析

实现理论上无限层级的组织部门机构,例如理事会->经理部门->销售部->外宣部->我;

实现方法

使用List

知道最多几层机构的情况下,foreach不断排序列出,代码示例如下

public List<menu> listAllForRole() {
        List<SystemMenuEntity> systemRoleMenuEntities = getStatic();
        if (systemRoleMenuEntities.size()>0){
            //获取一级菜单
            for (SystemMenuEntity entity:systemRoleMenuEntities) {
                if (StringUtils.isBlank(entity.getParentId())) {
                    menu vo = new menu();
                    vo.setId(entity.getId());
                    vo.setName(entity.getUrl());
                    vo.setTitle(entity.getName());
                    vos.add(vo);
                }
            }
            for (menu vo : vos) {
                List<menu> chrildren = new ArrayList<>();
                for (SystemMenuEntity systemRoleMenuEntity : systemRoleMenuEntities) {
                    //二级菜单
                    if (vo.getId().equals(systemRoleMenuEntity.getParentId())) {
                        menu menu = new menu();
                        menu.setId(systemRoleMenuEntity.getId());
                        menu.setName(systemRoleMenuEntity.getUrl());
                        menu.setTitle(systemRoleMenuEntity.getName());
                        List<menu> grandChrildren = new ArrayList<>();
                        for (SystemMenuEntity roleMenuEntity : systemRoleMenuEntities) {
                            //三级菜单
                            if (menu.getId().equals(roleMenuEntity.getParentId())) {
                                menu menuVO = new menu();
                                menuVO.setId(roleMenuEntity.getId());
                                menuVO.setName(roleMenuEntity.getUrl());
                                menuVO.setTitle(roleMenuEntity.getName());

                                List<menu> buttonMenus = new ArrayList<>();
                                for (SystemMenuEntity buttonMenuEntity : systemRoleMenuEntities) {
                                    //四级按钮
                                    if (menuVO.getId().equals(buttonMenuEntity.getParentId())) {
                                        menu buttonmenuVO = new menu();
                                        buttonmenuVO.setId(buttonMenuEntity.getId());
                                        buttonmenuVO.setName(buttonMenuEntity.getUrl());
                                        buttonmenuVO.setTitle(buttonMenuEntity.getName());
                                        buttonMenus.add(buttonmenuVO);
                                    }
                                }
                                menuVO.setButton(buttonMenus);
                                grandChrildren.add(menuVO);
                            }
                        }
                        menu.setChildren(grandChrildren);
                        chrildren.add(menu);
                    }
                }
                vo.setChildren(chrildren);
            }
        }
        //}
        return vos;
使用Map

使用map加桶排序,进行递归查询

   public List<Object>listAllForRoleBetter(List<String> ids,int i) {
        List<SystemMenuVO> vos = new ArrayList<>();
        List<Object> mapVos = new ArrayList<>();
        List<String> sortProperties = new ArrayList<>();
        List<SystemMenuEntity> entities = getStatic();
        for (SystemMenuEntity entity:entities) {
            Map<String,Object> menuMap = new LinkedHashMap<>();
            if (StringUtils.isBlank(entity.getParentId())){
                menuMap.put("id",entity.getId());
                menuMap.put("name",entity.getUrl());
                menuMap.put("title",entity.getName());
                menuMap.put("access",0);
                menuMap.put("tChildren",menuChild(entity.getId(),entities,ids));
                mapVos.add(menuMap);
            }
        }
        return mapVos;
    }

    private List<?> menuChild(String id, List<SystemMenuEntity> entities,List<String> ids) {
        List<Object> child = new ArrayList<>();
        for (SystemMenuEntity entity:entities) {
            Map<String,Object> menuMap = new LinkedHashMap<>();
            if (id.equals(entity.getParentId())){
                menuMap.put("id",entity.getId());
                menuMap.put("name",entity.getUrl());
                menuMap.put("title",entity.getName());
                menuMap.put("access",0);
                menuMap.put("tChildren",menuChild(entity.getId(),entities,ids));
                child.add(menuMap);
            }
        }
        return child;
    }
使用Tree

两次循环完成树状结构

public List<SystemMenuVO> listAllForRoleMast(List<String> ids,int i) {
        List<String> sortProperties = new ArrayList<>();

        List<SystemMenuEntity> dataList = getStatic();
        Map<String,SystemMenuVO> nodeList = new HashMap();
        List<SystemMenuVO> vos = new ArrayList<>();
        for (SystemMenuEntity dataRecord: dataList) {
            List<SystemMenuVO> temp = new ArrayList<>();
            SystemMenuVO node = new SystemMenuVO();
            node.setId(dataRecord.getId());
            node.setName(dataRecord.getUrl());
            node.setTitle(dataRecord.getName());
            node.setSystemMenuVOS(temp);
            node.setAccess(0);
            node.setParentId(StringUtils.isBlank(dataRecord.getParentId())?"":dataRecord.getParentId());
            nodeList.put(node.getId(),node);
        }
        for (SystemMenuEntity dataRecord: dataList) {
            SystemMenuVO vo = (SystemMenuVO)nodeList.get(dataRecord.getId());
            if (StringUtils.isBlank(dataRecord.getParentId())){
                vos.add(vo);
            }else{
                ((SystemMenuVO)nodeList.get(dataRecord.getParentId())).getSystemMenuVOS().add(vo);
            }
        }
        return vos;
    }
    
生成静态数据
 public List<SystemMenuEntity> getStatic(){
        List<SystemMenuEntity> vo = new ArrayList<>();
        //一级父类
        for (int i = 0; i <5 ; i++) {
            List<SystemMenuEntity> temp = new ArrayList<>();
            SystemMenuEntity node = new SystemMenuEntity();
            node.setId(UUID.randomUUID().toString());
            node.setName("test"+i);
            node.setUrl("test"+i);
            node.setParentId(null);
            vo.add(node);
            for (int j = 0; j <5 ; j++) {
                SystemMenuEntity node1 = new SystemMenuEntity();
                node1.setId(UUID.randomUUID().toString());
                node1.setName("1test"+j);
                node.setUrl("test"+i);
                node1.setParentId(node.getId());
                vo.add(node1);
                for (int k = 0; k <5 ; k++) {
                    SystemMenuEntity node2 = new SystemMenuEntity();
                    node2.setId(UUID.randomUUID().toString());
                    node2.setName("2test"+1);
                    node.setUrl("test"+i);
                    node2.setParentId(node1.getId());
                    vo.add(node2);
                    for (int m = 0; m <5 ; m++) {
                        SystemMenuEntity node3 = new SystemMenuEntity();
                        node3.setId(UUID.randomUUID().toString());
                        node3.setName("3test"+1);
                        node.setUrl("test"+i);
                        node3.setParentId(node2.getId());
                        vo.add(node3);
                    }
                }
            }
        }
        return vo;
    }
测试方法
  public void testTree(){
        long begin;
        long end;

        begin = System.currentTimeMillis();
        List<Object> map4 = sysMenuService.listAllForRoleBetter(null, 0);
        end = System.currentTimeMillis();
        System.out.println(end-begin);
        System.out.println(JSON.toJSONString(map4));

        begin = System.currentTimeMillis();
        List<SystemMenuVO> map3 = sysMenuService.listAllForRoleMast(null, 0);
        end = System.currentTimeMillis();
        System.out.println(end-begin);
        System.out.println(JSON.toJSONString(map3));

        begin = System.currentTimeMillis();
        List<SystemMenuVO> map1 = sysMenuService.listAllForRole(null, 0);
        end = System.currentTimeMillis();
        System.out.println(end-begin);
        System.out.println(JSON.toJSONString(map1));
    }

测试结果

方法msmsms
list442720
map645533
tree223

结论

做如这样的排序的时候,需要考虑两个,你从数据库拿出来的结构是怎么样的,有规律的数据排序会更加快速;第二你的结构是否经常变化,如果不是那么经常进行增删操作,可以做到缓存里面,使用redis。业务总是变化的,如果你对前端一无所知你就得问清楚前台需要数据以及格式。对于无限层级数据操作,使用桶排序的思路,可以构建出属于你自己的二叉树结构。这种做法让我想起了,java中方法参数的引用,是值传递?还是引用传递?对于对象是引用的传递。最后欢迎大家指教交流!

无限级树(Java递归) 2007-02-08 10:26 这几天,用java写了一个无限极的树,递归写的,可能代码不够简洁,性能不够好,不过也算是练习,这几天再不断改进。前面几个小图标的判断,搞死我了。 package com.nickol.servlet; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.nickol.utility.DB; public class category extends HttpServlet { /** * The doGet method of the servlet. * * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setCharacterEncoding("utf-8"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); out .println(""); out.println(""); out.println(" Category" + "" + "body{font-size:12px;}" + "" + "" + ""); out.println(" "); out.println(showCategory(0,0,new ArrayList(),"0")); out.println(" "); out.println(""); out.flush(); out.close(); } public String showCategory(int i,int n,ArrayList frontIcon,String countCurrent){ int countChild = 0; n++; String webContent = new String(); ArrayList temp = new ArrayList(); try{ Connection conn = DB.GetConn(); PreparedStatement ps = DB.GetPs("select * from category where pid = ?", conn); ps.setInt(1, i); ResultSet rs = DB.GetRs(ps); if(n==1){ if(rs.next()){ webContent += "";//插入结尾的减号 temp.add(new Integer(0)); } webContent += " ";//插入站点图标 webContent += rs.getString("cname"); webContent += "\n"; webContent += showCategory(Integer.parseInt(rs.getString("cid")),n,temp,"0"); } if(n==2){ webContent += "\n"; }else{ webContent += "\n"; } while(rs.next()){ for(int k=0;k<frontIcon.size();k++){ int iconStatic = ((Integer)frontIcon.get(k)).intValue(); if(iconStatic == 0){ webContent += "";//插入空白 }else if(iconStatic == 1){ webContent += "";//插入竖线 } } if(rs.isLast()){ if(checkChild(Integer.parseInt(rs.getString("cid")))){ webContent += "";//插入结尾的减号 temp = (ArrayList)frontIcon.clone(); temp.add(new Integer(0)); }else{ webContent += "";//插入结尾的直角 } }else{ if(checkChild(Integer.parseInt(rs.getString("cid")))){ webContent += "";//插入未结尾的减号 temp = (ArrayList)frontIcon.clone(); temp.add(new Integer(1)); }else{ webContent += "";//插入三叉线 } } if(checkChild(Integer.parseInt(rs.getString("cid")))){ webContent += " ";//插入文件夹图标 }else{ webContent += " ";//插入文件图标 } webContent += rs.getString("cname"); webContent += "\n"; webContent += showCategory(Integer.parseInt(rs.getString("cid")),n,temp,countCurrent+countChild); countChild++; } webContent += "\n"; DB.CloseRs(rs); DB.ClosePs(ps); DB.CloseConn(conn); }catch(Exception e){ e.printStackTrace(); } return webContent; } public boolean checkChild(int i){ boolean child = false; try{ Connection conn = DB.GetConn(); PreparedStatement ps = DB.GetPs("select * from category where pid = ?", conn); ps.setInt(1, i); ResultSet rs = DB.GetRs(ps); if(rs.next()){ child = true; } DB.CloseRs(rs); DB.ClosePs(ps); DB.CloseConn(conn); }catch(Exception e){ e.printStackTrace(); } return child; } } --------------------------------------------------------------------- tree.js文件 function changeState(countCurrent,countChild){ var object = document.getElementById("level" + countCurrent + countChild); if(object.style.display=='none'){ object.style.display='block'; }else{ object.style.display='none'; } var cursor = document.getElementById("cursor" + countCurrent + countChild); if(cursor.src.indexOf("images/tree_minus.gif")>=0) {cursor.src="images/tree_plus.gif";} else if(cursor.src.indexOf("images/tree_minusbottom.gif")>=0) {cursor.src="images/tree_plusbottom.gif";} else if(cursor.src.indexOf("images/tree_plus.gif")>=0) {cursor.src="images/tree_minus.gif";} else {cursor.src="images/tree_minusbottom.gif";} var folder = document.getElementById("folder" + countCurrent + countChild); if(folder.src.indexOf("images/icon_folder_channel_normal.gif")>=0){ folder.src = "images/icon_folder_channel_open.gif"; }else{ folder.src = "images/icon_folder_channel_normal.gif"; }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值