List转多对多树形结构

在很多场景中我们需要将list转为多对多的数据结构,然后传给前端:如我们在查询菜单等场景,然而很多情况下不知道数据的层级,无从下手,下面我将我实现的一段代码贴出,供大家参考:

/**
 * @Auther: MR.rp
 * @Date: 2021/10/28 13:55
 * @Description: 树的继承者
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "树的继承父类")
@ToString
public class TreeMode<T> implements Cloneable {

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


    @ApiModelProperty(value = "父id,顶级父id为0")
    private  Integer  pid;

    @ApiModelProperty(value = "子集")
    private List<?  extends  TreeMode >  children;

    @Override
    public Object clone()  {

        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return  null;
    }

}

为简化代码,该代码使用了java8的代码编写,使用了lombok插件简化get,set方法,swagger的注释我也没有去掉,能看懂就行,实体类大家也可以自己写,根据自己的业务,选择继承上面的实体类;

/**
 * @Auther: MR.rp
 * @Date: 2021/10/28 14:32
 * @Description: 将list转换为树形
 */
public class TreeBuilder {
    
    /**
     * list转树形结构工具
     * @param allNodes
     * @return
     */
    public static  List<? extends TreeMode> treeList(List <? extends TreeMode> allNodes) {
        Stream<? extends TreeMode> stream = allNodes.stream().filter(permission -> permission.getPid().equals(0))
                                            .map(permission -> covert(permission, allNodes));
        List<? extends TreeMode> result = stream.collect(Collectors.toList());
        return result;
    }

    /**
     * 递归查找子树
     * @param permission
     * @param permissionList
     * @return
     */
    private static  TreeMode<? extends TreeMode> covert(TreeMode<? extends TreeMode > permission, List<? extends TreeMode> permissionList) {
        TreeMode<? extends TreeMode> node = (TreeMode<? extends TreeMode>) permission.clone();
        Stream<? extends TreeMode> stream = permissionList.stream().filter(subPermission -> subPermission.getPid().equals(permission.getId()))
                                            .map(subPermission -> covert(subPermission, permissionList));
        List<? extends TreeMode> children = stream.collect(Collectors.toList());
        node.setChildren(children);
        return node;
    }
}

以上为自己实现的代码,可能存在bug,仅供参考学习,欢迎指正,共同学习进步

在之前的代码虽然实现了转换树形结构,但是用的是Beanutils.copyproperties,似乎对泛型支持不太有好,
在测试中只拷贝了父类的属性,改用了深拷贝的方法,在子类实现的时候需要实现深拷贝的方法;
这里我也贴出自己的业务代码,仅供参考:

/**
 * <p>
 * 菜单权限表
 * </p>
 *
 * @author MR.RP
 * @since 2021-10-29
 */
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="Menu对象", description="菜单权限表")
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Menu   extends TreeMode implements Serializable,Cloneable{

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "路由路径")
    private String path;

    @ApiModelProperty(value = "路由对应name(英文)")
    private String name;

    @ApiModelProperty(value = "该路由对应的组件")
    private String component;

    @ApiModelProperty(value = "重定向的路由地址")
    private String redirect;

    @ApiModelProperty(value = "排序字段")
    private Integer orderNo;

    @ApiModelProperty(value = "是否忽略权限")
    private String ignoreAuth;

    @ApiModelProperty(value = "是否只生成菜单")
    private String ignoreRoute;

    @ApiModelProperty(value = "是否为单级路由")
    private String single;


    @ApiModelProperty(value = "权限")
    private String permission;

    @ApiModelProperty(value = "是否删除")
    @TableLogic
    private Integer isDel;

    @ApiModelProperty(value = "创建时间")
    @TableField(fill = FieldFill.INSERT)
    private String gmtCreate;

    @ApiModelProperty(value = "更新时间")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private String gmtModified;

    @ApiModelProperty(value = "菜单组件")
    @TableField(exist=false)
    private MenuMeta menuMeta;


    @Override
    public Object clone()  {
        Menu menu = (Menu)super.clone();
        if(menuMeta!= null){
            MenuMeta meta =(MenuMeta) menuMeta.clone();
            menu.setMenuMeta(menuMeta);
        }
        return menu;
    }

}

下面是属性实体类:

/**
 * <p>
 * 菜单组件表
 * </p>
 *
 * @author MR.RP
 * @since 2021-10-29
 */
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="MenuMeta对象", description="菜单组件表")
public class MenuMeta implements Serializable,Cloneable {

    private static final long serialVersionUID = 1L;

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

    @ApiModelProperty(value = "菜单id")
    private Integer menuId;

    @ApiModelProperty(value = "路由名称")
    private String title;

    @ApiModelProperty(value = "图标")
    private String icon;

    @ApiModelProperty(value = "是否不显示该菜单")
    @TableField("hideMenu")
    private String hidemenu;

    @ApiModelProperty(value = "是否不在选项卡中显示")
    @TableField("hideBreadcrumb")
    private String hidebreadcrumb;

    @ApiModelProperty(value = "当页面为外部页面时的路径")
    @TableField("frameSrc")
    private String framesrc;

    @ApiModelProperty(value = "是否缓存")
    @TableField("ignoreKeepAlive")
    private String ignorekeepalive;

    @ApiModelProperty(value = "是否为链接")
    @TableField("isLink")
    private String islink;

    @Override
    public Object clone()  {

        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return  null;
    }

}

为了让代码更加通用所以在写util时候用了部分泛型,如果发现有bug欢迎留言,共同学习,
嗯,还在努力学习中…大家有什么建议吗?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值