java树形结构返回左右值查询结果

这里是数据库左右值结构的设计

https://my.oschina.net/wuzhaohui/blog/113194

找了很多左右值的文章,全部都是讲数据库的,但最终要返回给前端的树形结构却没有,便自己试着写了一个,
数据库结构和数据

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for menu
-- ----------------------------
DROP TABLE IF EXISTS `menu`;
CREATE TABLE `menu`  (
  `id` int(10) NOT NULL,
  `menuName` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `lft` int(10) NULL DEFAULT NULL,
  `rgt` int(10) NULL DEFAULT NULL,
  `level` int(10) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of menu
-- ----------------------------
INSERT INTO `menu` VALUES (1, '主菜单', 1, 30, 1);
INSERT INTO `menu` VALUES (2, '子菜单1', 2, 9, 2);
INSERT INTO `menu` VALUES (3, '子子菜单1', 3, 8, 3);
INSERT INTO `menu` VALUES (4, '子子子菜单1', 4, 7, 4);
INSERT INTO `menu` VALUES (5, '子菜单3', 10, 15, 2);
INSERT INTO `menu` VALUES (6, '子子子子菜单1', 5, 6, 5);
INSERT INTO `menu` VALUES (7, '子子菜单3', 11, 14, 3);
INSERT INTO `menu` VALUES (8, '子子子菜单3', 12, 13, 4);
INSERT INTO `menu` VALUES (9, '子菜单2', 16, 19, 2);
INSERT INTO `menu` VALUES (10, '子菜单4', 22, 29, 2);
INSERT INTO `menu` VALUES (11, '子子菜单4', 23, 28, 3);
INSERT INTO `menu` VALUES (12, '子子子菜单4', 24, 25, 4);
INSERT INTO `menu` VALUES (13, '子子菜单2', 17, 18, 3);
INSERT INTO `menu` VALUES (14, '子菜单5', 20, 21, 2);
INSERT INTO `menu` VALUES (15, '子子子菜单4-1', 26, 27, 4);

SET FOREIGN_KEY_CHECKS = 1;

代码如下

// 实体类
@Data
@TableName("menu")
public class Menu implements Serializable {

    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    @TableField("menuName")
    private String menuName;

    @TableField("lft")
    private Integer lft;

    @TableField("rgt")
    private Integer rgh;

    @TableField("level")
    private Integer level;

    @TableField(exist=false)
    private List<Menu> list;


}

数据递归方法

 public void treeStructure(Menu menuParent, List<Menu> menuList) {
        for (Menu son : menuList) {
            // 查找根节点下子节点 子节点的左值 - 1 == 根节点的左值  或者  子节点右值 + 1 == 根节点右值
            // 例如    1  -  6
            //    2 - 3    4 - 5
            if (son.getLft() - 1 == menuParent.getLft() || son.getRgh() + 1 == menuParent.getRgh()) {
                // 这里先判断根节点的子节点是否有值,没有赋值, 有了就添加  直接赋值会覆盖之前的节点
                if (menuParent.getList() == null) {
                    menuParent.setList(new ArrayList<>(Collections.singletonList(son)));
                } else {
                    menuParent.getList().addAll(new ArrayList<>(Collections.singletonList(son)));
                }
            }
            // 这里是判断 特殊节点的 如下
            //       1  -  12
            // 2 - 5  6 - 9  10 - 11
            // 3 - 4  7 - 8
            // 这里的 6 - 7  左值 - 1 != 根节点的左值   右值 + 1 != 根节点右值
            // 这里的if判断是防止出现  7 - 8 被放置在  2 - 3 节点下
            else if ((menuParent.getRgh() > son.getRgh() && menuParent.getLft() < son.getLft())) {
                for (Menu menu : menuParent.getList()) {
                    // 循环根节点的子节点 保证他们的层级是一样的  该节点的左值 大于其他节点的右值  或者 该节点的右值小于其他节点的左值
                    // 2 - 5  6 - 9  10 - 11    6 - 9  左值大于 2-5 的右值   右值小于 10 - 11 的左值
                    boolean b1 = (menu.getRgh() < son.getLft() || menu.getLft() > son.getRgh())
                            && menu.getLevel().equals(son.getLevel());
                    if (b1) {
                        // 进入这个方法 就不用判断 list 是否为null  上面的判断已经添加了,如果这里报空 就该检查是否左右值错误
                        menuParent.getList().addAll(new ArrayList<>(Collections.singletonList(son)));
                        // 这里结束本次循环,防止重复加入
                        break;
                    }
                }
            }
        }
        // 这里递归调用方法, 把根节点的子节点再次当成根节点传入方法
        if (menuParent.getList() != null) {
            for (Menu menu : menuParent.getList()) {
                treeStructure(menu, menuList);
            }
        }
    }

数据结构

{
	"id": 1,
	"menuName": "主菜单",
	"lft": 1,
	"rgh": 30,
	"level": 1,
	"list": [
		{
			"id": 2,
			"menuName": "子菜单1",
			"lft": 2,
			"rgh": 9,
			"level": 2,
			"list": [
				{
					"id": 3,
					"menuName": "子子菜单1",
					"lft": 3,
					"rgh": 8,
					"level": 3,
					"list": [
						{
							"id": 4,
							"menuName": "子子子菜单1",
							"lft": 4,
							"rgh": 7,
							"level": 4,
							"list": [
								{
									"id": 6,
									"menuName": "子子子子菜单1",
									"lft": 5,
									"rgh": 6,
									"level": 5,
									"list": null
								}
							]
						}
					]
				}
			]
		},
		{
			"id": 5,
			"menuName": "子菜单3",
			"lft": 10,
			"rgh": 15,
			"level": 2,
			"list": [
				{
					"id": 7,
					"menuName": "子子菜单3",
					"lft": 11,
					"rgh": 14,
					"level": 3,
					"list": [
						{
							"id": 8,
							"menuName": "子子子菜单3",
							"lft": 12,
							"rgh": 13,
							"level": 4,
							"list": null
						}
					]
				}
			]
		},
		{
			"id": 9,
			"menuName": "子菜单2",
			"lft": 16,
			"rgh": 19,
			"level": 2,
			"list": [
				{
					"id": 13,
					"menuName": "子子菜单2",
					"lft": 17,
					"rgh": 18,
					"level": 3,
					"list": null
				}
			]
		},
		{
			"id": 14,
			"menuName": "子菜单5",
			"lft": 20,
			"rgh": 21,
			"level": 2,
			"list": null
		},
		{
			"id": 10,
			"menuName": "子菜单4",
			"lft": 22,
			"rgh": 29,
			"level": 2,
			"list": [
				{
					"id": 11,
					"menuName": "子子菜单4",
					"lft": 23,
					"rgh": 28,
					"level": 3,
					"list": [
						{
							"id": 12,
							"menuName": "子子子菜单4",
							"lft": 24,
							"rgh": 25,
							"level": 4,
							"list": null
						},
						{
							"id": 15,
							"menuName": "子子子菜单4-1",
							"lft": 26,
							"rgh": 27,
							"level": 4,
							"list": null
						}
					]
				}
			]
		}
	]
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值