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编程:将具有父子关系的数据库表数据转换为树形结构,支持无限层级
在平时的开发工作中,经常遇到这样一个场景,在数据库中存储了具有父子关系的数据,需要将这些数据以树形结构的形式在界面上进行展示.本文的目的是提供了一个通用的编程模型,解决将具有父子关系的数据转换成树形结 ...
随机推荐
- 使用docker安装nginx并配置端口转发
使用docker安装并运行nginx命令: docker run --name=nginx -p 80:80 -d docker.io/nginx 使用命令: docker exec -it ngin ...
- JAVAWEB开发下常见中文乱码问题解决
JAVA环境下处理中文乱码问题一直是很多人困扰的问题,像URL传参乱码,写进数据库乱码,服务写中文文字图片乱码处理及导出PDF乱码. 1:安装中文支持 yum groupinstall "f ...
- python5.2文件写入
fh=open(r"C:\55.txt","w")#文件编写新的文字,替代原有的文字!w:writedata = "努力让生活更美好!"fh ...
- Hive: Reflect UDF
Reflect UDF JAVA类和方法通常用于处理用户希望在hive中使用的确切的函数.相比与封装一个UDF然后调用这个方法,这些 方法主要通过反射UDF去调用.Reflect使用Java反射去实例 ...
- java_Collection、Map、泛型的使用
Collection集合 集合按照其存储结构可以分为两大类,分别是 单列集合 java.util.Collection 双列集合 java.util.Map Collection:单列集合类的根接口, ...
- JDK 1.8 中文 API CHM
链接: https://pan.baidu.com/s/1AiJn6RM1KoEL1n_96qoQhQ 提取码: n2ya
- Revit二开---Schemachema扩展数据
一.什么是Schema Schema是Revit扩展数据的技术关键词,revit到这里,需要对Revit二开基础有一定了解. 二.Schema架构 建立revit扩展数据第 ...
- C#LeetCode刷题之#605-种花问题( Can Place Flowers)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3724 访问. 假设你有一个很长的花坛,一部分地块种植了花,另一部 ...
- .NET 跨平台框架Avalonia UI: 填坑指北(一):熟悉UI操作
Avalonia 是一个跨平台的 .NET UI 框架,支持 Windows.Linux.Mac OSX... (以及Android IOS soon..) 本篇主要介绍Avalonia开发过程和L ...
- Xor 思维题
Xor 思维题 题目描述 小\(Q\)与小\(T\)正在玩一棵树.这棵树有\(n\)个节点,编号为 \(1\),\(2\) \(3...n\),由\(n-1\)条边连接,每个节点有一个权值\(w_i\ ...