业务场景

通常我们前端需要一个树形的导航菜单或者分类菜单,如后台权限管理中的权限树,亦或者下面例子中商城系统的商品分类多级菜单(一般为三级菜单)

数据库设计

数据库设计,采用parentId来指向自己的父级菜单,如:

  1. CREATE TABLE `pms_category` (
  2. `cat_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '分类id',
  3. `name` char(50) DEFAULT NULL COMMENT '分类名称',
  4. `parent_cid` bigint(20) DEFAULT NULL COMMENT '父分类id',
  5. `cat_level` int(11) DEFAULT NULL COMMENT '层级',
  6. `show_status` tinyint(4) DEFAULT NULL COMMENT '是否显示[0-不显示,1显示]',
  7. `sort` int(11) DEFAULT NULL COMMENT '排序',
  8. `icon` char(255) DEFAULT NULL COMMENT '图标地址',
  9. `product_unit` char(50) DEFAULT NULL COMMENT '计量单位',
  10. `product_count` int(11) DEFAULT NULL COMMENT '商品数量',
  11. PRIMARY KEY (`cat_id`)
  12. ) ENGINE=InnoDB AUTO_INCREMENT=1433 DEFAULT CHARSET=utf8mb4 COMMENT='商品三级分类';

java组装树形结构

之前的做法是通过sql自连接来查出树形结构数据,但是效率不高,我们知道单表查询效率是最高的,我们可以一次查出所有数据,通过java8的新特性 stream来处理数据,stream是通过CPU计算实现,效率极高,具体用法可以参考:

Java 8新特性之 Lambd和StreamAPI

下面是处理数据的两个主要方法:

  1. @Override
  2. public List<CategoryEntity> listWithTree() {
  3. // 1. 先查出所有分类数据
  4. List<CategoryEntity> categories = baseMapper.selectList(null);
  5. // 2. 找出所有一级分类
  6. // 在映射到每个一级分类 添加它的子分类类
  7. return categories.stream()
  8. .filter(o -> o.getParentCid() == 0)
  9. // 给每个一级分类加子分类
  10. .peek(o -> o.setChildrens(getChildCategoryList(o, categories)))
  11. // 排序
  12. .sorted(Comparator.comparingInt(CategoryEntity::getSort))
  13. // 收集
  14. .collect(Collectors.toList());
  15. }
  16. // 根据当前分类 找出子类, 并通过递归找出子类的子类
  17. private List<CategoryEntity> getChildCategoryList(CategoryEntity currMenu, List<CategoryEntity> categories) {
  18. return categories.stream().filter(o -> o.getParentCid().equals(currMenu.getCatId()))
  19. .peek(o -> o.setChildrens(getChildCategoryList(o, categories)))
  20. .sorted(Comparator.comparingInt(CategoryEntity::getSort))
  21. .collect(Collectors.toList());
  22. }

实体类变动

  • 为了拼接子菜单,需要将实体类增加一个属性childrens
  • 排序时需要用到sort属性,该字段在数据库可能为null,采用三元运算将其默认为0,防止排序异常
  1. @TableField(exist = false)
  2. private List<CategoryEntity> childrens;
  3. public Integer getSort() {
  4. return sort == null ? 0 : sort;
  5. }

返回数据效果

业务场景

通常我们前端需要一个树形的导航菜单或者分类菜单,如后台权限管理中的权限树,亦或者下面例子中商城系统的商品分类多级菜单(一般为三级菜单)

数据库设计

数据库设计,采用parentId来指向自己的父级菜单,如:

  1. CREATE TABLE `pms_category` (
  2. `cat_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '分类id',
  3. `name` char(50) DEFAULT NULL COMMENT '分类名称',
  4. `parent_cid` bigint(20) DEFAULT NULL COMMENT '父分类id',
  5. `cat_level` int(11) DEFAULT NULL COMMENT '层级',
  6. `show_status` tinyint(4) DEFAULT NULL COMMENT '是否显示[0-不显示,1显示]',
  7. `sort` int(11) DEFAULT NULL COMMENT '排序',
  8. `icon` char(255) DEFAULT NULL COMMENT '图标地址',
  9. `product_unit` char(50) DEFAULT NULL COMMENT '计量单位',
  10. `product_count` int(11) DEFAULT NULL COMMENT '商品数量',
  11. PRIMARY KEY (`cat_id`)
  12. ) ENGINE=InnoDB AUTO_INCREMENT=1433 DEFAULT CHARSET=utf8mb4 COMMENT='商品三级分类';

java组装树形结构

之前的做法是通过sql自连接来查出树形结构数据,但是效率不高,我们知道单表查询效率是最高的,我们可以一次查出所有数据,通过java8的新特性 stream来处理数据,stream是通过CPU计算实现,效率极高,具体用法可以参考:

Java 8新特性之 Lambd和StreamAPI

下面是处理数据的两个主要方法:

  1. @Override
  2. public List<CategoryEntity> listWithTree() {
  3. // 1. 先查出所有分类数据
  4. List<CategoryEntity> categories = baseMapper.selectList(null);
  5. // 2. 找出所有一级分类
  6. // 在映射到每个一级分类 添加它的子分类类
  7. return categories.stream()
  8. .filter(o -> o.getParentCid() == 0)
  9. // 给每个一级分类加子分类
  10. .peek(o -> o.setChildrens(getChildCategoryList(o, categories)))
  11. // 排序
  12. .sorted(Comparator.comparingInt(CategoryEntity::getSort))
  13. // 收集
  14. .collect(Collectors.toList());
  15. }
  16. // 根据当前分类 找出子类, 并通过递归找出子类的子类
  17. private List<CategoryEntity> getChildCategoryList(CategoryEntity currMenu, List<CategoryEntity> categories) {
  18. return categories.stream().filter(o -> o.getParentCid().equals(currMenu.getCatId()))
  19. .peek(o -> o.setChildrens(getChildCategoryList(o, categories)))
  20. .sorted(Comparator.comparingInt(CategoryEntity::getSort))
  21. .collect(Collectors.toList());
  22. }

实体类变动

  • 为了拼接子菜单,需要将实体类增加一个属性childrens
  • 排序时需要用到sort属性,该字段在数据库可能为null,采用三元运算将其默认为0,防止排序异常
  1. @TableField(exist = false)
  2. private List<CategoryEntity> childrens;
  3. public Integer getSort() {
  4. return sort == null ? 0 : sort;
  5. }

返回数据效果

java返回树形结构的正确姿势的更多相关文章

  1. Java实现树形结构的数据转Json格式

    在项目中难免会用到树形结构,毕竟这是一种常用的组织架构.楼主这里整理了两个实现的版本,可以直接拿来使用,非常方便. 楼主没有单独建项目,直接在以前的一个Demo上实现的.第一种,看下面代码: pack ...

  2. Java创建树形结构算法实例

    在JavaWeb的相关开发中经常会涉及到多级菜单的展示,为了方便菜单的管理需要使用数据库进行支持,本例采用相关算法讲数据库中的条形记录进行相关组装和排序讲菜单组装成树形结构. 首先是需要的JavaBe ...

  3. java 实现树形结构

    package tree; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Font; import java ...

  4. JAVA获取树形结构

    package com.nnmzkj.common.dto; import lombok.Data; import java.io.Serializable;import java.util.Arra ...

  5. java后台树形结构展示---懒加载

    一.数据库设计 二.实体类:entity import com.joyoung.cloud.security.common.validatedGroup.Add;import com.joyoung. ...

  6. 2020年大厂Java面试前复习的正确姿势(800+面试题附答案解析)

    前言 个人觉得面试也像是一场全新的征程,失败和胜利都是平常之事.所以,劝各位不要因为面试失败而灰心. 丧失斗志.也不要因为面试通过而沾沾自喜,等待你的将是更美好的未来,继续加油! 本篇分享的面试题内容 ...

  7. 使用 Java8 Optional 的正确姿势(转)

    我们知道 Java 8 增加了一些很有用的 API, 其中一个就是 Optional. 如果对它不稍假探索, 只是轻描淡写的认为它可以优雅的解决 NullPointException 的问题, 于是代 ...

  8. [转] 使用 Java8 Optional 的正确姿势

    [From] https://unmi.cc/proper-ways-of-using-java8-optional/ 我们知道 Java 8 增加了一些很有用的 API, 其中一个就是 Option ...

  9. Java编程:将具有父子关系的数据库表数据转换为树形结构,支持无限层级

    在平时的开发工作中,经常遇到这样一个场景,在数据库中存储了具有父子关系的数据,需要将这些数据以树形结构的形式在界面上进行展示.本文的目的是提供了一个通用的编程模型,解决将具有父子关系的数据转换成树形结 ...

随机推荐

  1. Android 的Glide、TabLayout、RecyclerView(下一章补充)。

    今天的内容主要和一些依赖有关, //Glide依赖implementation 'com.github.bumptech.glide:glide:4.11.0'//Google Design依赖//n ...

  2. 用 Python 可以实现侧脸转正脸?我也要试一下!

    作者 | 李秋键 责编 | Carol 封图 | CSDN 下载自视觉中国 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例 ...

  3. WebService简单Demo

    看了网上好多关于webservice的例子,基本上对初学者来说都是模棱两可云里雾里,现在,我将网上关于webservice的讲解提炼出来,通过一个最简单使用并且方便的例子,告诉大家什么是webserv ...

  4. JS 图片跟随鼠标移动案例

    css代码 img { position: absolute; /* top: 2px; */ width: 50px; height: 50px; } HTML代码 <img src=&quo ...

  5. Ant Design Pro入门教程,安装,运行(V5 Typescript版)

    [前言] 找了很多Admin模板,最后还是看中了AntDesignPro这个阿里巴巴开源的Admin框架,长这样(还行吧,目前挺主流的): 官网地址:https://pro.ant.design/in ...

  6. Oracle 存储过程 批量插入测试数据

    有时候需要做DB的效率测试时,需要模拟大量数据.可以根据一条原始数据,通过执行存储过程拷贝出大量数据: CREATE OR REPLACE PROCEDURE proc_msw_strsql IS i ...

  7. 2020-07-08:mysql只有一个表a,什么情况下会造成死锁,解决办法是什么?

    福哥答案2020-07-08: 表锁是不会出现死锁的,但锁等待现象是有可能的.行锁是行级别的,有可能出现死锁.环形等待死锁和唯一键死锁 很常见. 避免死锁方法:1.减少事务操作的记录数.2.约定按相同 ...

  8. 利用BeautifulSoup去除HTML指定标签和去除注释

    去除指定标签 from bs4 import BeautifulSoup #去除属性ul [s.extract() for s in soup("ul")] # 去除属性svg [ ...

  9. IOS 单例崩溃分析 2014-12-10 15:46:36

    单例模式是常用的模式,但是在单例应用中偶或引发崩溃让人匪夷所思.其实真的是单例引起的吗?未必.但是现象都指向了是单例引起的.今天我亲身经历了看似崩溃在单例上的一个例子,但实则不是,今天做个记录用于今后 ...

  10. 编写有提示的listbox控件 2008-06-29 17:13

    在MFC中几乎所有的控件都有信息提示,而惟有listbox却没有这样的一个功能,每当我们把鼠标移到listbox上控件时,啥玩意儿都没有是不是很气馁啊,所以我今天特地写了一个简单的有提示的listbo ...