JAVA List 转树形结构

package com.java.utils;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.sf.entity.dto.BaseTree;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 树形机构转化工具
 * @author lizh
 */
public class TreeUtils<T extends BaseTree> {
    /** 父级时分组会出现异常,给默认值 **/
    private static final String DEFAULT_FIST_KEY = "[_0-_df_key_-0_]";
    private TreeUtils(){}

    /**
     *集合转成树形结构
     * @param cols 集合数据
     * @return 返回树形列表
     */
    public static<T> List<T> col2Tree(Collection<? extends BaseTree> cols){
        return col2Tree(cols,false, null);
    }

    /**
     *集合转成树形结构
     * @param cols 集合数据
     * @param isSort  是否排序
     * @return 返回树形列表
     */
    public static<T> List<T> col2Tree(Collection<? extends BaseTree> cols, boolean isSort){
        return col2Tree(cols, isSort, false, null);
    }

    /**
     *集合转成树形结构
     * @param cols 集合数据
     * @param rootParentIds 根节点上级Id
     * @return 返回树形列表
     */
    public static<T> List<T>col2Tree(Collection<? extends BaseTree> cols, Object[] rootParentIds){
        return col2Tree(cols,false, rootParentIds);
    }

    /**
     *集合转成树形结构
     * @param cols 集合数据
     * @param isSort  是否排序
     * @param rootParentIds 根节点上级Id
     * @return 返回树形列表
     */
    public static<T> List<T> col2Tree(Collection<? extends  BaseTree> cols, boolean isSort, Object[] rootParentIds){
        return (List<T>)col2Tree((Collection<BaseTree>)cols, isSort, false, rootParentIds);
    }

    /**
     *集合转成树形结构
     * @param cols 集合数据
     * @param isSort  是否排序
     * @param isReversed 是否倒叙
     * @param rootParentIds 根节点上级Id
     * @return 返回树形列表
     */
    public static<T> List<T> col2Tree(Collection<? extends  BaseTree> cols, boolean isSort, boolean isReversed, Object[] rootParentIds){
        return (List<T>)doCol2Tree((Collection<BaseTree>)cols, isSort, isReversed, rootParentIds);
    }

    /**
     *集合转成树形结构
     * @param cols 集合数据
     * @param isSort  是否排序
     * @param isReversed 是否倒叙
     * @param rootParentIds 根节点上级Id
     * @return 返回树形列表
     */
    private static List<BaseTree> doCol2Tree(Collection<BaseTree> cols, boolean isSort, boolean isReversed, Object[] rootParentIds){
        if(CollectionUtils.isEmpty(cols)){ return Collections.emptyList(); }
        Set<Object> rootParentIdSet = ArrayUtils.isNotEmpty(rootParentIds) ?
                    Sets.newHashSet(rootParentIds) : Sets.newHashSet() ;
        Map<Object,List<BaseTree>> nodeMap = cols.stream()
                .filter( t -> Objects.nonNull(t) && !isRoot(rootParentIdSet, t.getParentId()))
                .collect(Collectors.groupingBy(BaseTree::getParentId));
        cols.forEach(ch -> ch.setChildren(nodeMap.get(ch.getId())));
        List<BaseTree> resultList = cols.stream().filter(t -> isRoot(rootParentIdSet, t.getParentId())).collect(Collectors.toList());
        if(isSort){ treeSort(resultList, false); }
        return resultList;
    }

    /**
     * list转树形结构,没有父级ID自动跳为一级菜单
     * @param cols 源数据列表
     * @param isSort 是否排序
     * @param isReversed 是否倒叙
     * @return 树形列表
     */
    private static List<BaseTree> doAutoCol2Tree(Collection<BaseTree> cols, boolean isSort, boolean isReversed){
        if(CollectionUtils.isEmpty(cols)){ return Collections.emptyList(); }
        Map<Object,List<BaseTree>> nodeMap = cols.stream().filter(Objects::nonNull).map(t -> {
            if(Objects.isNull(t.getParentId())){
                t.setParentId(DEFAULT_FIST_KEY);
            }
            return t;
        }).collect(Collectors.groupingBy(BaseTree::getParentId));
        cols.forEach(ch -> {
            ch.setChildren(nodeMap.get(ch.getId()));
            nodeMap.remove(ch.getId());
        });
        List<Object> firstIds = new ArrayList<>();
        nodeMap.values().forEach(lst -> lst.forEach(t -> firstIds.add(t.getId())));
        List<BaseTree> resultList = cols.stream().filter(t ->{
            if(firstIds.contains(t.getId())){
                if(Objects.equals(DEFAULT_FIST_KEY,t.getParentId())){
                    t.setParentId(null);
                }
                return true;
            }
            return false;
        }).collect(Collectors.toList());
        if(isSort){ treeSort(resultList, isReversed);}
        return resultList;
    }

    /**
     * list转树形结构,没有父级ID自动跳为一级菜单
     * @param cols 源数据列表
     * @param isSort 是否排序
     * @param isReversed 是否倒叙
     * @return 树形列表
     */
    public static<T> List<T> autoCol2Tree(Collection<? extends  BaseTree> cols, boolean isSort, boolean isReversed){
        return (List<T>) doAutoCol2Tree((Collection<BaseTree>) cols, isSort, isReversed);
    }

    /**
     * list转树形结构,没有父级ID自动跳为一级菜单
     * @param cols 源数据列表
     * @param isSort 是否排序
     * @return 树形列表
     */
    public static<T> List<T> autoCol2Tree(Collection<? extends  BaseTree> cols, boolean isSort){
        return  autoCol2Tree(cols,isSort,false);
    }

    /**
     * list转树形结构,没有父级ID自动跳为一级菜单
     * @param cols 源数据列表
     * @return 树形列表
     */
    public static<T> List<T> autoCol2Tree(Collection<? extends  BaseTree> cols){
        return  autoCol2Tree((Collection)cols,false,false);
    }

    /** 判断是否为根节点 **/
    private static boolean isRoot(Set<Object> rootParentIdSet, Object parentId){
        return Objects.isNull(parentId) || rootParentIdSet.contains(parentId);
    }

    /** 对各级菜单进行排序 **/
    private static void treeSort(List<BaseTree> treeList, boolean reversed){
        if(CollectionUtils.isEmpty(treeList) || Objects.equals(treeList.size(),1)){ return; }
        List<BaseTree> sortList = treeList.stream().sorted(
                reversed ? Comparator.comparing(BaseTree::getSort).reversed():Comparator.comparing(BaseTree::getSort)
        ).collect(Collectors.toList());
        treeList.clear();
        treeList.addAll(sortList);
        treeList.forEach(t -> treeSort(t.getChildren(),reversed));
    }

    public static void main(String[] args) {
        BaseTree node1a = new BaseTree(1,null,"一级目录1",1);
        BaseTree node2a = new BaseTree(2,"","一级目录2",2);
        BaseTree node3a = new BaseTree(3,null,"一级目录3",3);
        BaseTree node4a = new BaseTree(4,0,"一级目录4",4);
        BaseTree node5a = new BaseTree(5,-1,"一级目录5",5);

        BaseTree node21a = new BaseTree(6,1,"二级目录1",1);
        BaseTree node22a = new BaseTree(7,1,"二级目录2",2);
        BaseTree node23a = new BaseTree(8,1,"二级目录3",3);
        BaseTree node24a = new BaseTree(9,2,"二级目录4",4);
        BaseTree node25a = new BaseTree(10,3,"二级目录5",5);

        BaseTree node31a = new BaseTree(11,8,"3级目录1",1);
        BaseTree node32a = new BaseTree(12,8,"3级目录2",2);
        BaseTree node33a = new BaseTree(13,10,"3级目录3",3);
        BaseTree node34a = new BaseTree(14,100,"3级目录4",4);
        BaseTree node35a = new BaseTree(15,16,"3级目录5",5);


        BaseTree node41a = new BaseTree(16,15,"4级目录1",1);
        BaseTree node42a = new BaseTree(17,11,"4级目录2",2);
        BaseTree node43a = new BaseTree(18,15,"4级目录3",3);
        BaseTree node44a = new BaseTree(19,11,"4级目录4",4);

        BaseTree node54a = new BaseTree(20,17,"5级目录5",5);
        BaseTree node55a = new BaseTree(21,18,"5级目录5",5);

        BaseTree node61a = new BaseTree(22,21,"6级目录5",5);

        List<BaseTree> lists = Lists.newArrayList(node3a,node1a,node2a,node5a,node4a,
                node21a,node22a,node23a,node24a,node25a,
                node31a,node32a,node33a,node34a,node35a,
                node41a,node42a,node43a,node44a,
                node54a,node55a,
                node61a
        );

        System.out.println(JSON.toJSONString(col2Tree(lists,true,false, new Object[]{"",0,-1,null,100})));

        System.out.println(JSON.toJSONString(autoCol2Tree(lists,true,false)));

    }

}




package com.java.entity.dto;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.List;

/**
 * 树形基础类
 * @author lizh
 */
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
public class BaseTree implements Serializable {
    private static final long serialVersionUID = 1L;
    /** 本级ID **/
    private Object id;
    /** 父级ID **/
    private Object parentId;
    /** 本级名称 **/
    private String name;
    /** 排序号,越小越靠前 **/
    private Integer sort;
    /** 子级列表 **/
    List<BaseTree> children;

    public BaseTree(Object id, Object parentId, String name, Integer sort) {
        this.id = id;
        this.parentId = parentId;
        this.name = name;
        this.sort = sort;
    }
}

若分享转发请附上原文地址。

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值