java返回树形结构的正确姿势
业务场景
通常我们前端需要一个树形的导航菜单或者分类菜单,如后台权限管理中的权限树,亦或者下面例子中商城系统的商品分类多级菜单(一般为三级菜单)
数据库设计
数据库设计,采用parentId来指向自己的父级菜单,如:
CREATE TABLE `pms_category` (
`cat_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '分类id',
`name` char(50) DEFAULT NULL COMMENT '分类名称',
`parent_cid` bigint(20) DEFAULT NULL COMMENT '父分类id',
`cat_level` int(11) DEFAULT NULL COMMENT '层级',
`show_status` tinyint(4) DEFAULT NULL COMMENT '是否显示[0-不显示,1显示]',
`sort` int(11) DEFAULT NULL COMMENT '排序',
`icon` char(255) DEFAULT NULL COMMENT '图标地址',
`product_unit` char(50) DEFAULT NULL COMMENT '计量单位',
`product_count` int(11) DEFAULT NULL COMMENT '商品数量',
PRIMARY KEY (`cat_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1433 DEFAULT CHARSET=utf8mb4 COMMENT='商品三级分类';
java组装树形结构
之前的做法是通过sql自连接来查出树形结构数据,但是效率不高,我们知道单表查询效率是最高的,我们可以一次查出所有数据,通过java8的新特性 stream来处理数据,stream是通过CPU计算实现,效率极高,具体用法可以参考:
Java 8新特性之 Lambd和StreamAPI
下面是处理数据的两个主要方法:
@Override
public List<CategoryEntity> listWithTree() {
// 1. 先查出所有分类数据
List<CategoryEntity> categories = baseMapper.selectList(null);
// 2. 找出所有一级分类
// 在映射到每个一级分类 添加它的子分类类
return categories.stream()
.filter(o -> o.getParentCid() == 0)
// 给每个一级分类加子分类
.peek(o -> o.setChildrens(getChildCategoryList(o, categories)))
// 排序
.sorted(Comparator.comparingInt(CategoryEntity::getSort))
// 收集
.collect(Collectors.toList());
}
// 根据当前分类 找出子类, 并通过递归找出子类的子类
private List<CategoryEntity> getChildCategoryList(CategoryEntity currMenu, List<CategoryEntity> categories) {
return categories.stream().filter(o -> o.getParentCid().equals(currMenu.getCatId()))
.peek(o -> o.setChildrens(getChildCategoryList(o, categories)))
.sorted(Comparator.comparingInt(CategoryEntity::getSort))
.collect(Collectors.toList());
}
实体类变动
- 为了拼接子菜单,需要将实体类增加一个属性childrens
- 排序时需要用到sort属性,该字段在数据库可能为null,采用三元运算将其默认为0,防止排序异常
@TableField(exist = false)
private List<CategoryEntity> childrens;
public Integer getSort() {
return sort == null ? 0 : sort;
}
返回数据效果
业务场景
通常我们前端需要一个树形的导航菜单或者分类菜单,如后台权限管理中的权限树,亦或者下面例子中商城系统的商品分类多级菜单(一般为三级菜单)
数据库设计
数据库设计,采用parentId来指向自己的父级菜单,如:
CREATE TABLE `pms_category` (
`cat_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '分类id',
`name` char(50) DEFAULT NULL COMMENT '分类名称',
`parent_cid` bigint(20) DEFAULT NULL COMMENT '父分类id',
`cat_level` int(11) DEFAULT NULL COMMENT '层级',
`show_status` tinyint(4) DEFAULT NULL COMMENT '是否显示[0-不显示,1显示]',
`sort` int(11) DEFAULT NULL COMMENT '排序',
`icon` char(255) DEFAULT NULL COMMENT '图标地址',
`product_unit` char(50) DEFAULT NULL COMMENT '计量单位',
`product_count` int(11) DEFAULT NULL COMMENT '商品数量',
PRIMARY KEY (`cat_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1433 DEFAULT CHARSET=utf8mb4 COMMENT='商品三级分类';
java组装树形结构
之前的做法是通过sql自连接来查出树形结构数据,但是效率不高,我们知道单表查询效率是最高的,我们可以一次查出所有数据,通过java8的新特性 stream来处理数据,stream是通过CPU计算实现,效率极高,具体用法可以参考:
Java 8新特性之 Lambd和StreamAPI
下面是处理数据的两个主要方法:
@Override
public List<CategoryEntity> listWithTree() {
// 1. 先查出所有分类数据
List<CategoryEntity> categories = baseMapper.selectList(null);
// 2. 找出所有一级分类
// 在映射到每个一级分类 添加它的子分类类
return categories.stream()
.filter(o -> o.getParentCid() == 0)
// 给每个一级分类加子分类
.peek(o -> o.setChildrens(getChildCategoryList(o, categories)))
// 排序
.sorted(Comparator.comparingInt(CategoryEntity::getSort))
// 收集
.collect(Collectors.toList());
}
// 根据当前分类 找出子类, 并通过递归找出子类的子类
private List<CategoryEntity> getChildCategoryList(CategoryEntity currMenu, List<CategoryEntity> categories) {
return categories.stream().filter(o -> o.getParentCid().equals(currMenu.getCatId()))
.peek(o -> o.setChildrens(getChildCategoryList(o, categories)))
.sorted(Comparator.comparingInt(CategoryEntity::getSort))
.collect(Collectors.toList());
}
实体类变动
- 为了拼接子菜单,需要将实体类增加一个属性childrens
- 排序时需要用到sort属性,该字段在数据库可能为null,采用三元运算将其默认为0,防止排序异常
@TableField(exist = false)
private List<CategoryEntity> childrens;
public Integer getSort() {
return sort == null ? 0 : sort;
}
返回数据效果

java返回树形结构的正确姿势的更多相关文章
- Java实现树形结构的数据转Json格式
在项目中难免会用到树形结构,毕竟这是一种常用的组织架构.楼主这里整理了两个实现的版本,可以直接拿来使用,非常方便. 楼主没有单独建项目,直接在以前的一个Demo上实现的.第一种,看下面代码: pack ...
- Java创建树形结构算法实例
在JavaWeb的相关开发中经常会涉及到多级菜单的展示,为了方便菜单的管理需要使用数据库进行支持,本例采用相关算法讲数据库中的条形记录进行相关组装和排序讲菜单组装成树形结构. 首先是需要的JavaBe ...
- java 实现树形结构
package tree; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Font; import java ...
- JAVA获取树形结构
package com.nnmzkj.common.dto; import lombok.Data; import java.io.Serializable;import java.util.Arra ...
- java后台树形结构展示---懒加载
一.数据库设计 二.实体类:entity import com.joyoung.cloud.security.common.validatedGroup.Add;import com.joyoung. ...
- 2020年大厂Java面试前复习的正确姿势(800+面试题附答案解析)
前言 个人觉得面试也像是一场全新的征程,失败和胜利都是平常之事.所以,劝各位不要因为面试失败而灰心. 丧失斗志.也不要因为面试通过而沾沾自喜,等待你的将是更美好的未来,继续加油! 本篇分享的面试题内容 ...
- 使用 Java8 Optional 的正确姿势(转)
我们知道 Java 8 增加了一些很有用的 API, 其中一个就是 Optional. 如果对它不稍假探索, 只是轻描淡写的认为它可以优雅的解决 NullPointException 的问题, 于是代 ...
- [转] 使用 Java8 Optional 的正确姿势
[From] https://unmi.cc/proper-ways-of-using-java8-optional/ 我们知道 Java 8 增加了一些很有用的 API, 其中一个就是 Option ...
- Java编程:将具有父子关系的数据库表数据转换为树形结构,支持无限层级
在平时的开发工作中,经常遇到这样一个场景,在数据库中存储了具有父子关系的数据,需要将这些数据以树形结构的形式在界面上进行展示.本文的目的是提供了一个通用的编程模型,解决将具有父子关系的数据转换成树形结 ...
随机推荐
- Android RecyclerView的补充。
明天写吧.. 今天写,然后再写今天的内容,虽然结课了,我们还是得学习,所以如果我学习了一些知识,不出意外每天会持续更新的. RecyclerView其实是可以完全代替ListView的存在, 但是为啥 ...
- echarts全国疫情统计可视化地图(第一阶段)
DBUtil.java package com.helloechart; import java.sql.Connection; import java.sql.DriverManager; impo ...
- DB2 SQL Error: SQLCODE=-1585, SQLSTATE=54048
DB2 执行SQL报错: DB2 SQL Error: SQLCODE=-1585, SQLSTATE=54048 你建的db2数据库没有建足够大的临时表空间,新建一个足够大的临时表空间 1.创建数据 ...
- java 接口一
一 接口的概念 接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的”类”. 接口只描述所应该具备的方法,并没有具体实现,具体的实现由接口的实现类(相当于接口 的子类)来完成.这样将功能的 ...
- 聊聊Java内省Introspector
前提 这篇文章主要分析一下Introspector(内省,应该读xing第三声,没有找到很好的翻译,下文暂且这样称呼)的用法.Introspector是一个专门处理JavaBean的工具类,用来获取J ...
- Promise.then返回的是什么?
console.log((function cook(){ console.log('开始做饭.'); var p = new Promise(function(resolve, reject){ / ...
- kafka-clients 1.0 高阶API消费消息(未完)
消费消息的请求(按序) org/apache/kafka/common/requests/RequestHeader org/apache/kafka/common/requests/ApiVersi ...
- SSM框架整合练习——一个简单的文章管理系统
使用SSM框架搭建的简易文章管理系统,实现了简单的增删改查功能. @ 目录 开发工具版本: 最终的项目结构 IDEA+Maven搭建项目骨架 1. 新建Maven项目: 2. 在新建的项目中添加所需要 ...
- Jmeter 常用函数(3)- 详解 __RandomString
如果你想查看更多 Jmeter 常用函数可以在这篇文章找找哦 https://www.cnblogs.com/poloyy/p/13291704.html 作用 根据指定的字符产生一个随机字符串 语法 ...
- Jmeter 常用函数(9)- 详解 __UUID
如果你想查看更多 Jmeter 常用函数可以在这篇文章找找哦 https://www.cnblogs.com/poloyy/p/13291704.html 作用 返回 伪随机类型4 通用唯一标识符 语 ...