java构建树形结构的方式

构建树形结构

废话少说,直接上代码

方式一

1、定义实体类

public class Category {

    private Long id;
    private String name;
    private Long parentId;
    private List<Category> children;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Long getParentId() {
        return parentId;
    }

    public void setParentId(Long parentId) {
        this.parentId = parentId;
    }

    public List<Category> getChildren() {
        return children;
    }

    public void setChildren(List<Category> children) {
        this.children = children;
    }

    public Category(Long id, String name, Long parentId) {
        this.id = id;
        this.name = name;
        this.parentId = parentId;
    }
}

工具类

private static List<Category> categories = new ArrayList<>();

static {
    // 绑定初始化一个Category的数据
    categories.add(new Category(1L, "一级分类-1", null));
    categories.add(new Category(2L, "一级分类-1-1", 1L));
    categories.add(new Category(3L, "一级分类-1-2", 1L));
    categories.add(new Category(30L, "一级分类-1-2-1", 3L));
    categories.add(new Category(4L, "一级分类-2", null));
    categories.add(new Category(5L, "一级分类-2-1", 4L));
    categories.add(new Category(6L, "一级分类-3", null));
    categories.add(new Category(7L, "一级分类-3-1", 6L));
    // 子节点
}

public static void main(String[] args) {
    String treeJson = JSONUtil.toJsonPrettyStr(parentList01());
    System.out.println(treeJson);
}

private static List<Category> parentList01(){
    List<Category> parentList = categories.stream().filter(category -> category.getParentId() == null).collect(Collectors.toList());
    for (Category category : parentList) {
        category.setChildren(buildChildren(category.getId(),categories));
    }
    return parentList;
}

private static List<Category> buildChildren(Long id, List<Category> categories) {
    List<Category> children = new ArrayList<>();
    for (Category category : categories) {
        if (category.getParentId() == null){
            continue;
        }
        if (category.getParentId().equals(id)){
            children.add(category);
        }
    }
    for (Category child : children) {
        child.setChildren(buildChildren(child.getId(),categories));
    }
    return children;
}

方式二

利用Map集合

@Override
public Result currentLeftMenu() {
    // 获取认证主体
    Subject subject = SecurityUtils.getSubject();
    ActiveUser activeUser = (ActiveUser) subject.getPrincipal();
    Integer userId = activeUser.getSysUser().getId();
    // 根据用户ID 和 菜单权限查询 权限
    List<SysPermissionVO> sysPermissionVOS = sysPermissionMapper.selectUserPermission(userId, Constant.PERMISSION_TYPE_MENU);
    // 菜单容器
    Map<Integer, SysPermissionVO> menu = new HashMap<>();

    for (SysPermissionVO sysPermissionVO : sysPermissionVOS) {
        // 获取菜单中的父ID
        Integer parentId = sysPermissionVO.getParentId();
        // 判断父ID是否是一级菜单
        if (parentId.equals(Constant.MENU_LV1)) {
            sysPermissionVO.setChildren(new ArrayList<SysPermissionVO>());
            // key 菜单的ID value
            menu.put(sysPermissionVO.getId(), sysPermissionVO);
        }
    }
    // 给1一级菜单赋二级菜单
    for (SysPermissionVO sysPermissionVO : sysPermissionVOS) {
        Integer parentId = sysPermissionVO.getParentId();
        if (menu.containsKey(parentId)) {
            SysPermissionVO sysPermissionVO1 = menu.get(parentId);
            sysPermissionVO1.getChildren().add(sysPermissionVO);
        }
    }
    Collection<SysPermissionVO> values = menu.values();
    // 返回给controller
    return new Result(values);
}

方式三:stream流方式

public List<CategoryEntity> listWithTree() {
    //1、查出所有分类
    List<CategoryEntity> entities = baseMapper.selectList(null);

    //2、组装成父子的树形结构
    //2.1)、找到所有的一级分类,给children设置子分类
    return entities.stream()
        // 过滤找出一级分类
        .filter(categoryEntity -> categoryEntity.getParentCid() == 0)
        // 处理,给一级菜单递归设置子菜单
        .peek(menu -> menu.setChildren(getChildless(menu, entities)))
        // 按sort属性排序
        .sorted(Comparator.comparingInt(menu -> (menu.getSort() == null ? 0 : menu.getSort())))
        .collect(Collectors.toList());
}

/**
 * 递归查找所有菜单的子菜单
 */
private List<CategoryEntity> getChildless(CategoryEntity root, List<CategoryEntity> all) {
    return all.stream()
        .filter(categoryEntity -> categoryEntity.getParentCid().equals(root.getCatId()))
        .peek(categoryEntity -> {
            // 找到子菜单
            categoryEntity.setChildren(getChildless(categoryEntity, all));
        })
        .sorted(Comparator.comparingInt(menu -> (menu.getSort() == null ? 0 : menu.getSort())))
        .collect(Collectors.toList());
}

另一个

public List<CategoryEntity> listWithLambda() {

    List<CategoryEntity> categorys = baseMapper.selectList(Wrappers.<CategoryEntity>lambdaQuery().orderByDesc(CategoryEntity::getCatId))
    List<CategoryEntity> entities = new ArrayList<>(categorys);
    Map<Long, List<CategoryEntity>> longListNavigableMap = entities.stream().collect(Collectors.groupingBy(CategoryEntity::getParentCid));

    List<CategoryEntity> res = entities.stream().peek(entity -> {
        if (longListNavigableMap.containsKey(entity.getCatId())) {
            entity.setChildren(longListNavigableMap.get(entity.getCatId()));
        }
    }).filter(entity -> entity.getCatLevel() == 1).sorted(Comparator.comparingInt(menu -> (menu.getSort() == null ? 0 : menu.getSort()))).collect(Collectors.toList());

    return res;
}

方式四:基于Hutool进行构建

导入hutool的依赖,请参考hutool官网

实体类

@Data
@TableName("pms_category")
@AllArgsConstructor
public class CategoryEntity implements Serializable {
	private static final long serialVersionUID = 1L;

	/**
	 * 分类id
	 */
	@TableId
	private Long catId;
	/**
	 * 分类名称
	 */
	private String name;
	/**
	 * 父分类id
	 */
	private Long parentCid;
	/**
	 * 层级
	 */
	private Integer catLevel;
	/**
	 * 是否显示[0-不显示,1显示]
	 */
	@TableLogic(value = "1",delval = "0")
	private Integer showStatus;
	/**
	 * 排序
	 */
	private Integer sort;
	/**
	 * 图标地址
	 */
	private String icon;
	/**
	 * 计量单位
	 */
	private String productUnit;
	/**
	 * 商品数量
	 */
	private Integer productCount;

	/**
	 * 所有子分类
	 */
	@JsonInclude(JsonInclude.Include.NON_EMPTY)
	@TableField(exist = false)
	private List<CategoryEntity> children;

}

service

public class TreeUtils{
    public List<Tree<Long>> listWithTree() {
        ArrayList<CategoryEntity> dataList = Lists.newArrayList();
        dataList.add(new CategoryEntity(1L,"电子产品",0L,1,1,0,"/images/electronics.png","件",50,null));
        dataList.add(new CategoryEntity(2L,"手机通讯",1L,2,1,0,"/images/electronics.png","件",150,null));
        dataList.add(new CategoryEntity(3L,"家用电器",1L,2,1,0,"/images/electronics.png","件",250,null));
        List<CategoryEntity> entities = dataList;
        if (!CollectionUtil.isEmpty(entities)) {
            List<TreeNode<Long>> list = entities.
                    stream().
                    map(CategoryServiceImpl::getLongTreeNode).
                    collect(Collectors.toList());
            return TreeUtil.build(list, 0L);
        }
        return Collections.emptyList();
    }

    private static TreeNode<Long> getLongTreeNode(CategoryEntity item) {
	    TreeNode<Long> treeNode = new TreeNode<>();
	    treeNode.setId(item.getCatId());
	    treeNode.setParentId(item.getParentCid());
	    treeNode.setName(item.getName());
	    treeNode.setWeight(item.getSort());
	    Map<String, Object> extra = new HashMap<>();
	    extra.put("showStatus", item.getShowStatus());
	    extra.put("catLevel", item.getCatLevel());
	    extra.put("icon", item.getIcon());
	    extra.put("productUnit", item.getProductUnit());
	    extra.put("productCount", item.getProductCount());
	    treeNode.setExtra(extra);
	    return treeNode;
	}
} 

测试

public static void main(String[] args) {
    List<Tree<Long>> trees = listWithTree1();
    System.out.println(JSONUtil.toJsonPrettyStr(trees));
}

方式五

基于mybatisplus的@TableName里面的resultMap属性,当发生查询时,会根据配置的xml查询SQL进行查询

mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xw.mapper.FuncMapper">
    <resultMap id="thCloudFuncMap" type="com.xw.entity.Func">
        <id column="id" property="id"/>
        <result column="creator" property="creator"/>
        <result column="creator_name" property="creatorName"/>
        <result column="updater" property="updater"/>
        <result column="updater_name" property="updaterName"/>
        <result column="code" property="code"/>
        <result column="name" property="name"/>
        <result column="icon" property="icon"/>
        <result column="note" property="note"/>
        <result column="parent_id" property="parentId"/>
        <result column="sort" property="sort"/>
        <result column="component_name" property="componentName"/>
        <result column="type" property="type"/>
        <collection column="id" property="children" select="findByParentId" ofType="com.telehot.tpf.dev.rolemenu.entity.ThCloudFunc">
        </collection>
    </resultMap>


    <select id="findByParentId" resultMap="funcMap">
        SELECT * FROM func WHERE parent_id = #{parentId}
    </select>


    <select id="findAll" resultMap="funcMap">
        SELECT * FROM func where is_disabled = 0
    </select>
</mapper>

实体类

@TableName(value = "func", resultMap = "funcMap")
public class Func extends Entity {


    /**
     * 编码
     */
    private String code;

    /**
     * 菜单名称
     */
    private String name;

    /**
     * 图标
     */
    private String icon;

    /**
     * 图标
     */
    private String selectIcon;

    /**
     * 说明
     */

    private String note;

    /**
     * 父类ID
     */
    private Long parentId;

    /**
     * 排序
     */
    private Integer sort;

    /**
     * 类型
     */
    private Integer type;

    /**
     * 路径
     */
    private String path;

    /**
     * 应用id
     */
    private String appId;

    /***
     * 组件名
     */
    private String componentName;

    /**
     * 层级
     */
    private Integer tier;


    @TableField(exist = false)
    private List<Func> children;

}

最后,来一个饭后甜点:java实现 tree结构模糊搜索功能
https://blog.youkuaiyun.com/xiaoshitou_s/article/details/127563692

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值