天天看点

树形结构数据转换

作者:天天年年天天8

菜单表结构

create table sys_auth
(
	id bigint auto_increment
		primary key,
	parent_id bigint default 0 not null comment '父id',
	name varchar(50) not null comment '名称(菜单名)',
	code varchar(50) null comment '权限编码',
	web_code varchar(50) not null comment '前端权限编码(路由名/按钮名)',
	auth_type tinyint not null comment '权限类型(菜单,目录,按钮,权限)',
	sort int null comment '排序',
	icon varchar(50) null comment '菜单图标',
	path varchar(255) null comment '路由地址',
	component varchar(255) null comment '组件路径',
	frame_flag tinyint default 0 not null comment '是否外链',
	frame_url varchar(255) null comment '外链地址',
	cache_flag tinyint default 1 not null comment '是否缓存',
	show_flag tinyint default 1 not null comment '是否显示',
	state tinyint not null comment '状态',
	creator varchar(50) not null comment '创建账号',
	create_time datetime not null comment '创建时间',
	updator varchar(50) null comment '更新账号',
	update_time datetime null comment '更新时间',
	remark varchar(255) null comment '备注',
	contains_code varchar(255) null comment '包含权限'
)
comment '系统权限' charset=utf8mb4;           

将平行的数据转成树状结构数据给前端展示

方法1:数据实现接口,用工具类遍历组装数据

package com.hfw.common.util;

import java.util.List;

/**
 * 数结构数据
 * @author farkle
 * @date 2022-04-06
 */
public interface ListTree {
    Long getId();
    Long getParentId();

    Integer getSort();
    void setSort(Integer sort);

    Integer getLevel();
    void setLevel(Integer level);

    List<? extends ListTree> getChildren();
    void setChildren(List<? extends ListTree> children);
}           
package com.hfw.common.util;

import java.util.*;

/**
 * List工具类
 * @author farkle
 * @date 2022-04-06
 */
public class ListUtil {
    /**
     * 将平面list转换成树结构
     * @param list
     * @return
     */
    public static List listTotree(List<? extends ListTree> list) {
        Map<Long, List<ListTree>> map = new HashMap<>();
        List result = new ArrayList<>();
        for (ListTree acl : list) {
            if(acl.getSort()==null){
                acl.setSort(-1);
            }
            if (acl.getParentId() == 0) {
                acl.setLevel(1);
                result.add(acl);
            } else {
                List children = map.get(acl.getParentId());
                if (children == null) {
                    children = new ArrayList<>();
                    map.put(acl.getParentId(), children);
                }
                children.add(acl);
            }
        }
        tree(result, map);
        if(map.size()>0){
            map.forEach( (id,ele)->{
                result.addAll(ele);
            });
        }
        return result;
    }

    /**
     * 将平面list递归转换成树结构
     * @param list
     * @param map
     */
    private static void tree(List<ListTree> list, Map<Long, List<ListTree>> map) {
        list.sort((ListTree m, ListTree n) -> {
            if (m.getSort() == null || n.getSort() == null) {
                return (int) (m.getId() - n.getId());
            }
            if(m.getSort()==null){
                return 1;
            }
            if(n.getSort()==null){
                return 0;
            }
            return m.getSort() - n.getSort();
        });
        for (ListTree acl : list) {
            List<ListTree> children = map.remove(acl.getId());
            if (children != null) {
                for (ListTree c : children) {
                    c.setLevel(acl.getLevel() + 1);
                }
                acl.setChildren(children);
                tree(children, map);
            }
        }
    }

}           

方法2(推荐): 利用java8stream API组装

package com.hfw.common.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @date 2023-01-31
 */
public class TreeUtils {

    /**
     * @param list             源数据
     * @param setChildListFn   设置递归的方法
     * @param idFn             获取id的方法
     * @param pidFn            获取父id的方法
     * @param getRootCondition 获取根节点的条件
     * @return 将List 转换成 Tree
     */
    public static <M, T> List<M> listToTree(List<M> list,
                                            Function<M, T> idFn,
                                            Function<M, T> pidFn,
                                            BiConsumer<M, List<M>> setChildListFn,
                                            Predicate<M> getRootCondition) {
        if(list==null || list.size()<=0){
            return null;
        }
        Map<T, List<M>> listMap = list.stream().collect(Collectors.groupingBy(pidFn));
        list.forEach(model -> setChildListFn.accept(model, listMap.get(idFn.apply(model))));
        return list.stream().filter(getRootCondition).collect(Collectors.toList());
    }

    public static <M> List<M> treeToList(List<M> source,
                                         Function<M, List<M>> getChildListFn,
                                         BiConsumer<M, List<M>> setChildListFn,
                                         Predicate<M> getRootCondition) {
        List<M> target = new ArrayList<>();
        if(source!=null && source.size()>0) {
            treeToList(source, target, getChildListFn);
            target.forEach(model -> setChildListFn.accept(model, null));
            target.addAll(target.stream().filter(getRootCondition).collect(Collectors.toList()));
        }
        return target;
    }

    private static <F> void treeToList(List<F> source,
                                       List<F> target,
                                       Function<F, List<F>> getChildListFn) {
        if(source!=null && source.size()>0) {
            target.addAll(source);
            source.forEach(model -> {
                List<F> childList = getChildListFn.apply(model);
                if(childList!=null && childList.size()>0) {
                    treeToList(childList, target, getChildListFn);
                }
            });
        }
    }

}           

组装菜单数据

@Override
    public List<SysAuthDTO> treeList(SysAuth sysAuth){
        List<SysAuthDTO> list = sysAuthMapper.treeList(sysAuth);
        //return ListUtil.listTotree(list);
        return TreeUtils.listToTree(list, SysAuthDTO::getId, SysAuthDTO::getParentId, SysAuthDTO::setChildren,
                (dto) -> dto.getParentId()==0 );
    }           

集成项目完整示例代码: ZNEW-ADMIN

https://gitee.com/hongy123/znew-admin

一个简单通用的springboot+vue3后台管理系统

继续阅读