首页 > 其他分享 >开发用工具类2.0:无侵入式的树形状工具类TreeUtils

开发用工具类2.0:无侵入式的树形状工具类TreeUtils

时间:2023-02-01 18:46:04浏览次数:42  
标签:return List param TreeUtils 工具 2.0 childField 节点 parentField

package cn.jow.util;


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

/**
 * 无侵入方式处理对象集合,树形状结构数据,无递归
 * <pre>
 *     功能:
 *          1:对象集合或者Map集合==>包含指定属性的指定值
 *
 *          2:对象集合或者Map集合==>Map<key,obj>
 *          3:对象集合或者Map集合==>Map<key,value>
 *          4:对象集合或者Map集合==>Map<key,List<obj>>
 *          5:对象集合或者Map集合==>Map<key,List<value>>
 *
 *          6:对象集合或者Map集合==>查找上层的全部节点或者指定层级节点
 *          7:对象集合或者Map集合==>查找上层的全部节点id或者指定层级节点id
 *          8:对象集合或者Map集合==>查找子层的全部节点或者指定层级节点
 *          9:对象集合或者Map集合==>查找子层的全部节点id或者指定层级节点id
 *
 *          10:对象集合或者Map集合<==>树形状结构
 *     特点:
 *          1.不会重新重新创建业务对象
 *          2.不改变对象排序,若要排序,请先排序好再使用
 *          3.仅仅需要jdk8就可以运行,不需要引入其他包
 *          4.自测通过,效率不差。
 *          5.都是基于java.util的特定处理代码,加入了一点点steam流的使用
 *          6.以下方法都没用递归,请自行了解最大递归深度
 *     疑问:
 *          1.总数不对可能因为环形结构的节点被抛弃
 *          2.总数不对可能因为有父节点id但父节点不存在的节点会被抛弃
 *          3.完全不支持多线程处理同一个源数据集合
 *      说明:
 *          所见即所得,希望你觉得好用。良心若不痛,删掉作者信息,占为己用都不碍事。
 * </pre>
 *
 * @author JunOneWolf
 * @version 2.0
 * @date 2023-02-01
 */

public class TreeUtils {
    private TreeUtils() {
    }
    //--------------------------------------是否包含某个属性的值------------------------------------------------------------------

    /**
     * 根据对象某个属性筛选部分对象
     *
     * @param srcList     源对象
     * @param equalsValue 比较字符串
     * @param attribute   取值字段
     * @param <T>         泛型
     * @return 包含指定属性的指定值
     */
    public static <T> boolean containsAttribute(String equalsValue, List<T> srcList, Function<T, ? extends String> attribute) {
        return Objects.nonNull(equalsValue) && Objects.nonNull(attribute)
                && Optional.ofNullable(srcList).orElse(new ArrayList<>()).stream()
                .anyMatch(s -> Objects.nonNull(s) && equalsValue.equals(attribute.apply(s)));
    }

    /**
     * 根据对象某个属性筛选部分对象
     *
     * @param srcList     源对象
     * @param equalsValue 比较字符串
     * @param attribute   取值字段
     * @return 包含指定属性的指定值
     */
    public static boolean containsAttribute(String equalsValue, List<Map<String, Object>> srcList, String attribute) {
        return Objects.nonNull(equalsValue) && Objects.nonNull(attribute)
                && Optional.ofNullable(srcList).orElse(new ArrayList<>()).stream()
                .anyMatch(s -> Objects.nonNull(s) && equalsValue.equals(s.get(attribute)));
    }

    //--------------------------------------筛选出对象属性存入到map中------------------------------------------------------------------

    /**
     * @param srcList  对象集合
     * @param keyField 字段的值作为key
     * @param <T>      泛型
     * @return Map<key, obj>
     */
    public static <T> Map<String, T> entityList2Map(List<T> srcList, Function<T, ? extends String> keyField) {
        return Optional.ofNullable(srcList).orElse(new ArrayList<>()).stream()
                .filter(s -> Objects.nonNull(s) && Objects.nonNull(keyField.apply(s)))
                .collect(Collectors.toMap(keyField, v -> v, (a, b) -> a));
    }

    /**
     * @param srcList    对象集合
     * @param keyField   字段的值作为key
     * @param valueField 字段的值作为value
     * @param <T>        泛型
     * @return Map<key, value>
     */
    public static <T> Map<String, ?> entityList2Map(List<T> srcList, Function<T, ? extends String> keyField, Function<T, ?> valueField) {
        return Optional.ofNullable(srcList).orElse(new ArrayList<>()).stream()
                .filter(s -> Objects.nonNull(s) && keyField.apply(s) != null && valueField.apply(s) != null)
                .collect(Collectors.toMap(keyField, valueField));
    }


    /**
     * @param srcList  对象集合
     * @param keyField 字段的值作为key
     * @param <T>      泛型
     * @return Map<key, List < obj>>
     */
    public static <T> Map<String, List<T>> entityList2Maps(List<T> srcList, Function<T, ? extends String> keyField) {
        return Optional.ofNullable(srcList).orElse(new ArrayList<>()).stream()
                .filter(s -> Objects.nonNull(s) && keyField.apply(s) != null)
                .collect(Collectors.groupingBy(keyField));
    }

    /**
     * @param srcList    对象集合
     * @param keyField   字段的值作为key
     * @param valueField 字段的值作为value
     * @param <T>        泛型
     * @return Map<key, List < value>>
     */
    public static <T> Map<String, List<String>> entityList2Maps(List<T> srcList, Function<T, ? extends String> keyField, Function<T, ? extends String> valueField) {
        return Objects.isNull(srcList) ? new HashMap<>() : srcList.stream()
                .filter(s -> Objects.nonNull(s) && Objects.nonNull(keyField.apply(s)) && Objects.nonNull(valueField.apply(s)))
                .collect(Collectors.groupingBy(keyField, Collectors.mapping(valueField, Collectors.toList())));
    }


    /**
     * @param srcList  源对象集合
     * @param keyField 字段的值作为key
     * @return Map<key, obj>
     */
    public static Map<String, Map<String, Object>> mapList2Map(List<Map<String, Object>> srcList, String keyField) {
        return Optional.ofNullable(srcList).orElse(new ArrayList<>()).stream()
                .filter(s -> Objects.nonNull(s) && Objects.nonNull(s.get(keyField)))
                .collect(Collectors.groupingBy(s -> s.get(keyField).toString(),
                        Collectors.collectingAndThen(Collectors.toList(), v -> v.get(0))));
    }

    /**
     * @param srcList    源对象集合
     * @param keyField   字段的值作为key
     * @param valueField 字段的值作为value
     * @return Map<key, value>
     */
    public static Map<String, Object> mapList2Map(List<Map<String, Object>> srcList, String keyField, String valueField) {
        return Optional.ofNullable(srcList).orElse(new ArrayList<>()).stream()
                .filter(s -> Objects.nonNull(s) && Objects.nonNull(s.get(keyField)))
                .collect(Collectors.groupingBy(s -> s.get(keyField).toString(),
                        Collectors.collectingAndThen(Collectors.toList(), v -> v.get(0).get(valueField))));
    }

    /**
     * @param srcList  源对象集合
     * @param keyField 字段的值作为key
     * @return Map<key, List < obj>>
     */
    public static Map<String, List<Map<String, Object>>> mapList2Maps(List<Map<String, Object>> srcList, String keyField) {
        return Optional.ofNullable(srcList).orElse(new ArrayList<>()).stream()
                .filter(s -> Objects.nonNull(s) && Objects.nonNull(s.get(keyField)))
                .collect(Collectors.groupingBy(s -> s.get(keyField).toString(), Collectors.toList()));
    }

    /**
     * @param srcList    源对象集合
     * @param keyField   字段的值作为key
     * @param valueField 字段的值作为value
     * @return Map<key, List < value>>
     */
    public static Map<String, List<Object>> mapList2Maps(List<Map<String, Object>> srcList, String keyField, String valueField) {
        return Optional.ofNullable(srcList).orElse(new ArrayList<>()).stream()
                .filter(s -> Objects.nonNull(s) && Objects.nonNull(s.get(keyField)))
                .collect(Collectors.groupingBy(s -> s.get(keyField).toString()
                        , Collectors.collectingAndThen(Collectors.toList()
                                , s -> s.stream().map(b -> b.get(valueField)).collect(Collectors.toList()))));

    }

    //----------------------------------查找上层集合------------------------------------------------------------------

    /**
     * 循环查找上级节点id
     *
     * @param srcArray    单列表节点
     * @param equalsId    目标查找id
     * @param childField  查找的字段
     * @param parentField 父节点字段
     * @param <T>         泛型
     * @return 上层对象节点集合(父, 爷顺序往上)
     */
    public static <T> List<T> findAllParentOfEntity(String equalsId, List<T> srcArray, Function<T, ? extends String> childField, Function<T, ? extends String> parentField) {
        return findParentOfEntity(equalsId, srcArray, childField, parentField, -1);
    }

    /**
     * 循环查找上级节点id
     *
     * @param srcArray    单列表节点
     * @param equalsId    目标查找id
     * @param childField  查找的字段
     * @param parentField 父节点字段
     * @param level       层级
     * @param <T>         泛型
     * @return 上层对象节点集合(父, 爷顺序往上)
     */
    public static <T> List<T> findParentOfEntity(String equalsId, List<T> srcArray, Function<T, ? extends String> childField, Function<T, ? extends String> parentField, int level) {
        List<T> result = new LinkedList<>();
        checkParam(childField, parentField);
        if (srcArray != null && srcArray.size() > 0) {
            Map<String, ?> map = entityList2Map(srcArray, childField, parentField);
            List<String> useIdList = findParentIdListByMap(map, equalsId, level);
            Map<String, List<T>> srcMap = entityList2Maps(srcArray, childField);
            useIdList.forEach(s -> result.addAll(srcMap.get(s)));
        }
        return new ArrayList<>(result);
    }

    /**
     * 循环查找上级节点id
     *
     * @param srcArray    单列表节点
     * @param childId     子节点id
     * @param childField  查找的字段
     * @param parentField 父节点字段
     * @return 顺序的上层对象节点集合
     */
    public static <T1, T2> List<Map<T1, T2>> findAllParentOfMap(Object childId, List srcArray, String childField, String parentField) {
        return findParentOfMap(childId, srcArray, childField, parentField, -1);
    }

    /**
     * 循环查找上级节点id
     *
     * @param srcArray    单列表节点
     * @param childId     子节点id
     * @param childField  查找的字段
     * @param parentField 父节点字段
     * @param level       层数
     * @return 顺序的上层对象节点集合
     */
    public static <T1, T2> List<Map<T1, T2>> findParentOfMap(Object childId, List srcArray, String childField, String parentField, int level) {
        List<Map<T1, T2>> result = new ArrayList<>();
        checkParam(childField, parentField);
        if (srcArray != null && srcArray.size() > 0 && childId != null) {
            List<String> userIdList = findParentIdListByMap(mapList2Map(srcArray, childField, parentField), childId.toString(), level);
            Map<String, List> idAndListMap = mapList2Maps(srcArray, childField);
            userIdList.forEach(s -> result.addAll(idAndListMap.get(s)));
        }
        return result;
    }

    /**
     * 循环查找上级节点id
     *
     * @param srcArray    单列表节点
     * @param childId     目标查找id
     * @param childField  查找的字段
     * @param parentField 父节点字段
     * @return 上层对象节点集合(自己, 父, 爷顺序往上)
     */
    public static List<String> findAllParentIdOfMap(Object childId, List srcArray, String childField, String parentField) {
        return findParentIdOfMap(childId, srcArray, childField, parentField, -1);
    }

    /**
     * 循环查找上级节点id
     *
     * @param srcArray    单列表节点
     * @param childId     目标查找id
     * @param childField  查找的字段
     * @param parentField 父节点字段
     * @return 上层对象节点集合(自己, 父, 爷顺序往上)
     */
    public static List<String> findParentIdOfMap(Object childId, List srcArray, String childField, String parentField, int level) {
        checkParam(childField, parentField);
        if (srcArray != null && srcArray.size() > 0 && childId != null) {
            return findParentIdListByMap(mapList2Map(srcArray, childField, parentField), childId.toString(), level);
        }
        return new ArrayList<>();
    }

    /**
     * 循环查找上级节点id
     *
     * @param srcArray    单列表节点
     * @param childId     目标查找id
     * @param childField  查找的字段
     * @param parentField 父节点字段
     * @param <T>         泛型
     * @return 上层对象节点集合(自己, 父, 爷顺序往上)
     */
    public static <T> List<String> findAllParentIdOfEntity(String childId, List<T> srcArray, Function<T, ? extends String> childField, Function<T, ? extends String> parentField) {
        return findParentIdListByMap(entityList2Map(srcArray, childField, parentField), childId, -1);
    }

    /**
     * 循环查找上级节点id
     *
     * @param srcArray    单列表节点
     * @param childId     目标查找id
     * @param childField  查找的字段
     * @param parentField 父节点字段
     * @param <T>         泛型
     * @return 上层对象节点集合(自己, 父, 爷顺序往上)
     */
    public static <T> List<String> findParentIdOfEntity(String childId, List<T> srcArray, Function<T, ? extends String> childField, Function<T, ? extends String> parentField, int level) {
        return findParentIdListByMap(entityList2Map(srcArray, childField, parentField), childId, level);
    }

    /**
     * 从map取出上级,一层一层,尽头或者重复就会则停止
     *
     * @param idAndParentIdMap 层级节点结构
     * @param id               对比的节点
     * @return 上层的id
     */
    private static List<String> findParentIdListByMap(Map idAndParentIdMap, String id, int level) {
        List<String> useIdList = new ArrayList<>();
        Map<String, String> tempIdAndParentIdMap = (Map<String, String>) idAndParentIdMap;
        while (tempIdAndParentIdMap.containsKey(id) && !useIdList.contains(id)) {
            if (level > 0) {
                level--;
            } else if (level == 0) {
                break;
            }
            useIdList.add(id);
            String tempId = tempIdAndParentIdMap.get(id);
            if (!tempIdAndParentIdMap.containsKey(tempId)) {
                //如果是最上层,就需要再添加一次
                useIdList.add(tempId);
            }
            id = tempId;
        }

        return useIdList;
    }

    //------------------------------------查找子节点---------------------------------------------------------------------------

    /**
     * 循环查找自己以及上级节点id
     *
     * @param srcArray    单列表节点
     * @param id          目标查找id
     * @param childField  查找的字段
     * @param parentField 父节点字段
     * @param <T>         泛型
     * @return 上层对象节点集合(父, 爷顺序往上)
     */
    public static <T> List<T> findAllChildOfEntity(String id, List<T> srcArray, Function<T, ? extends String> childField, Function<T, ? extends String> parentField) {
        return findChildOfEntity(id, srcArray, childField, parentField, -1);
    }

    /**
     * 循环查找自己以及上级节点id
     *
     * @param srcArray    单列表节点
     * @param id          目标查找id
     * @param childField  查找的字段
     * @param parentField 父节点字段
     * @param level       层级
     * @param <T>         泛型
     * @return 上层对象节点集合(父, 爷顺序往上)
     */
    public static <T> List<T> findChildOfEntity(String id, List<T> srcArray, Function<T, ? extends String> childField, Function<T, ? extends String> parentField, int level) {
        List<T> result = new LinkedList<>();
        checkParam(childField, parentField);
        if (srcArray != null && srcArray.size() > 0) {
            Map<String, List<T>> srcMap = entityList2Maps(srcArray, childField);
            List<String> childIdList = findChildIdListByMap(entityList2Maps(srcArray, parentField, childField), Collections.singletonList(id), level);
            childIdList.forEach(s -> result.addAll(srcMap.get(s)));
        }
        return result;
    }

    /**
     * 查找子节点
     *
     * @param srcArray    单列表节点
     * @param childId     子节点id
     * @param childField  查找的字段
     * @param parentField 父节点字段
     * @return 顺序的上层对象节点集合
     */
    public static <T1, T2> List<Map<T1, T2>> findAllChildOfMap(Object childId, List srcArray, String childField, String parentField) {
        return findChildOfMap(childId, srcArray, childField, parentField, -1);
    }

    /**
     * 查找子节点
     *
     * @param srcArray    单列表节点
     * @param childId     子节点id
     * @param childField  查找的字段
     * @param parentField 父节点字段
     * @param level       层级
     * @return 顺序的上层对象节点集合
     */
    public static <T1, T2> List<Map<T1, T2>> findChildOfMap(Object childId, List srcArray, String childField, String parentField, int level) {
        List<Map<T1, T2>> result = new ArrayList<>();
        checkParam(childField, parentField);
        if (srcArray != null && srcArray.size() > 0 && childId != null) {
            List<String> userIdList = findChildIdListByMap(mapList2Map(srcArray, childField, parentField), Collections.singletonList(childId.toString()), level);
            Map<String, List> idAndListMap = mapList2Maps(srcArray, childField);
            userIdList.forEach(s -> result.addAll(idAndListMap.get(s)));
        }
        return result;
    }

    /**
     * 查找子节点id
     *
     * @param srcArray    单列表节点
     * @param childId     目标查找id
     * @param childField  查找的字段
     * @param parentField 父节点字段
     * @return 上层对象节点集合(自己, 父, 爷顺序往上)
     */
    public static List<String> findAllChildIdOfMap(Object childId, List srcArray, String childField, String parentField) {
        return findChildIdOfMap(childId, srcArray, childField, parentField, -1);
    }

    /**
     * 查找子节点id
     *
     * @param srcArray    单列表节点
     * @param childId     目标查找id
     * @param childField  查找的字段
     * @param parentField 父节点字段
     * @param level       层级
     * @return 上层对象节点集合(自己, 父, 爷顺序往上)
     */
    public static List<String> findChildIdOfMap(Object childId, List srcArray, String childField, String parentField, int level) {
        checkParam(childField, parentField);
        if (childId == null || childId.toString().length() == 0) {
            return new ArrayList<>();
        }
        return findChildIdListByMap(mapList2Maps(srcArray, parentField, childField), Collections.singletonList(childId.toString()), level);
    }

    /**
     * 查找子节点id
     *
     * @param srcArray    单列表节点
     * @param childId     目标查找id
     * @param childField  查找的字段
     * @param parentField 父节点字段
     * @param <T>         泛型
     * @return 子节点id
     */
    public static <T> List<String> findAllChildIdOfEntity(String childId, List<T> srcArray, Function<T, ? extends String> childField, Function<T, ? extends String> parentField) {
        return findChildIdOfEntity(childId, srcArray, childField, parentField, -1);
    }

    /**
     * 查找子节点id
     *
     * @param srcArray    单列表节点
     * @param childId     目标查找id
     * @param childField  查找的字段
     * @param parentField 父节点字段
     * @param level       层级
     * @param <T>         泛型
     * @return 子节点id
     */
    public static <T> List<String> findChildIdOfEntity(String childId, List<T> srcArray, Function<T, ? extends String> childField, Function<T, ? extends String> parentField, int level) {
        checkParam(childField, parentField);
        return findChildIdListByMap(entityList2Maps(srcArray, parentField, childField), Collections.singletonList(childId), level);
    }


    /**
     * 查找子节点,过滤已经使用过的id。
     *
     * @param parentAndChildMap 层级节点结构
     * @param idList            选择的子节点数量
     */
    private static List<String> findChildIdListByMap(Map<String, List<String>> parentAndChildMap, List<String> idList, int level) {
        //防止重复字段
        Set<String> useIdSet = new HashSet<>();
        List<String> result = new ArrayList<>(parentAndChildMap.size());
        List<String> targetList = new LinkedList<>(idList);
        //一整层一整层的获取,
        while (targetList.size() > 0) {
            if (level > 0) {
                level--;
            } else if (level == 0) {
                break;
            }
            List<String> tempSonIdList = new LinkedList<>();
            for (String id : targetList) {
                List<String> childIdList = parentAndChildMap.get(id);
                if (childIdList != null && childIdList.size() > 0) {
                    //移除掉已使用的
                    childIdList.removeAll(useIdSet);
                    result.addAll(childIdList);
                    useIdSet.addAll(childIdList);
                    tempSonIdList.addAll(childIdList);
                }
            }
            targetList = tempSonIdList;
        }
        return result;
    }


    //------------------------------------树形状和集合的互转---------------------------------------------------------------------------

    /**
     * List<Map>生成树形状结构
     *
     * @param srcList     对象集合
     * @param childField  当前节点字段
     * @param parentField 上层节点字段
     * @param saveField   子节点集合的存储字段
     * @return 父节点为null或者为""的第一层集合
     */
    public static <T1, T2> List<Map<T1, T2>> mapList2Tree(List srcList, String childField, String parentField, String saveField) {
        checkParam(childField, parentField, saveField);
        List result = new LinkedList();
        Map<String, List<Map<T1, T2>>> linkMap = mapList2Maps(srcList, parentField);
        Optional.ofNullable(srcList).orElse(new ArrayList<>()).stream().filter(Objects::nonNull).forEach(s -> {
            Map map = (Map) s;
            Object parentId = map.get(parentField);
            if (parentId == null || parentId.toString().length() == 0) {
                result.add(s);
            }
            Object childId = map.get(childField);
            if (childId != null && childId.toString().length() > 0) {
                Optional.ofNullable(linkMap.get(childId.toString())).ifPresent(a -> map.put(saveField, a));
            }
        });
        return new ArrayList<>(result);
    }

    /**
     * List<Entity>生成树形状结构
     *
     * @param srcList     源集合
     * @param childField  子字段
     * @param parentField 父字段
     * @param saveField   子节点集合的存储字段
     * @param <T>         泛型
     * @return 父节点为null或者为""的第一层集合
     */
    public static <T> List<T> entityList2Tree(List<T> srcList, Function<T, ? extends String> childField, Function<T, ? extends String> parentField, Function<T, ? extends List<T>> saveField) {
        checkParam(childField, parentField, saveField);
        List<T> result = new ArrayList<>();
        Map<String, List<T>> linkMap = entityList2Maps(srcList, parentField);
        Optional.ofNullable(srcList).orElse(new ArrayList<>()).stream().filter(Objects::nonNull).forEach(s -> {
            String parentId = parentField.apply(s);
            if (parentId == null || parentId.length() == 0) {
                result.add(s);
            }
            String childId = childField.apply(s);
            if (childId != null && childId.length() > 0) {
                Optional.ofNullable(linkMap.get(childId)).ifPresent(a -> {
                            List<T> tempList = saveField.apply(s);
                            tempList.addAll(a);
                        }
                );
            }
        });
        return result;
    }

    /**
     * 一维的集合,获取符合条件的对象集合。
     * &&&温馨提示,每个对象的childField字段的关系依然存在&&&
     *
     * @param srcList    来源集合
     * @param childField 属性字段
     * @param <T>        泛型
     * @return 一维的集合
     */
    public static <T> List<T> tree2EntityList(List<T> srcList, Function<T, ? extends List<T>> childField) {
        return tree2EntityList(srcList, childField, -1);
    }

    /**
     * 一维的集合,获取符合条件的对象集合。
     * &&&温馨提示,每个对象的childField字段的关系依然存在&&&
     *
     * @param srcList    来源集合
     * @param childField 属性字段
     * @param level      层级
     * @param <T>        泛型
     * @return 一维的集合
     */
    public static <T> List<T> tree2EntityList(List<T> srcList, Function<T, ? extends List<T>> childField, int level) {
        checkParam(childField);
        if (srcList == null || srcList.size() == 0) {
            return new ArrayList<>();
        }
        List<T> result = new LinkedList<>(srcList);
        Set<T> useObj = new HashSet<>();
        List<T> targetList = new LinkedList<>(srcList);
        //一整层一整层的获取,
        while (targetList.size() > 0) {
            if (level > 0) {
                level--;
            } else if (level == 0) {
                break;
            }
            List<T> tempSonIdList = new LinkedList<>();
            for (T obj : targetList) {
                if (obj == null) {
                    continue;
                }
                List<T> childIdList = childField.apply(obj);
                if (childIdList != null && childIdList.size() > 0) {
                    //移除掉已使用的
                    childIdList.removeAll(useObj);
                    useObj.addAll(childIdList);
                    result.addAll(childIdList);
                    tempSonIdList.addAll(childIdList);
                }
            }
            targetList = tempSonIdList;
        }
        return new ArrayList<>(result);
    }

    /**
     * 树形状转化单一列表
     *
     * @param srcList    来源对象
     * @param childField 子节点对象
     * @param <T1>       泛型
     * @param <T2>       泛型
     * @return 单列表集合
     */
    public static <T1, T2> List<Map<T1, T2>> tree2MapList(List srcList, String childField) {
        return tree2MapList(srcList, childField, -1);
    }

    /**
     * 树形状转化单一列表
     *
     * @param srcList    来源对象
     * @param childField 子节点对象
     * @param level      层级
     * @param <T1>       泛型
     * @param <T2>       泛型
     * @return 单列表集合
     */
    public static <T1, T2> List<Map<T1, T2>> tree2MapList(List srcList, String childField, int level) {
        checkParam(childField);
        if (srcList == null || srcList.size() == 0) {
            return new ArrayList<>();
        }
        List<Map<T1, T2>> result = new LinkedList<>(srcList);
        Set<Map<T1, T2>> useObj = new HashSet<>();
        List<Map<T1, T2>> targetList = new LinkedList<>(srcList);
        //一整层一整层的获取,
        while (targetList.size() > 0) {
            if (level > 0) {
                level--;
            } else if (level == 0) {
                break;
            }
            List<Map<T1, T2>> tempSonIdList = new LinkedList<>();
            for (Map<T1, T2> obj : targetList) {
                if (obj == null) {
                    continue;
                }
                List<Map<T1, T2>> childIdList = (List<Map<T1, T2>>) obj.get(childField);
                if (childIdList != null && childIdList.size() > 0) {
                    //移除掉已使用的
                    childIdList.removeAll(useObj);
                    useObj.addAll(childIdList);
                    result.addAll(childIdList);
                    tempSonIdList.addAll(childIdList);
                }
            }
            targetList = tempSonIdList;
        }
        return new ArrayList<>(result);
    }

    /**
     * 检测使用的参数是否重复,相等
     */
    private static void checkParam(Object... array) {
        Set<String> objSet = new HashSet<>();
        for (Object param : array) {
            if (Objects.isNull(param) || param.toString().length() == 0) {
                throw new RuntimeException("编码参数异常");
            }
            objSet.add(param.toString());
        }
        //暂时只支持判定字符串
        if (objSet.size() != array.length) {
            throw new RuntimeException("编码参数异常");
        }
    }
}

  

标签:return,List,param,TreeUtils,工具,2.0,childField,节点,parentField
From: https://www.cnblogs.com/junonewolf/p/17083843.html

相关文章

  • Watt Toolkit v2.8.6 多功能游戏工具箱
    WattToolkitv2.8.6多功能游戏工具箱WattToolkit工具箱能够让Steam平台的玩家们享受更加出色的游戏体验,工具箱包含多种实用的功能,支持快速切换登录账号,玩家还可以通......
  • 分享两个好用的XSS漏扫工具(工具)
    =================免责声明:希望大家以遵守《网络安全法》相关法律,本团队发表此文章仅用于研究学习,切勿用于非法犯罪活动,对于恶意使用该工具造成的损失,和本团队无关。=======......
  • Java两大工具库:Commons和Guava(4)
    您好,我是湘王,这是我的51CTO博客。值此新春佳节,我给您拜年啦~祝您在新的一年中所求皆所愿,所行皆坦途,展宏“兔”,有钱“兔”,多喜乐,常安宁!在Nginx中提到过通过限流算法实现对后端......
  • Java两大工具库:Commons和Guava(4)
    您好,我是湘王,这是我的博客园。值此新春佳节,我给您拜年啦~祝您在新的一年中所求皆所愿,所行皆坦途,展宏“兔”,有钱“兔”,多喜乐,常安宁!   在Nginx中提到过通过限流算法......
  • 接口测试|Fiddler界面工具栏介绍(一)
    fiddler界面工具栏介绍(1)WinConfig:windows使用了一种叫做“AppContainer”的隔离技术,使得一些流量无法正常捕获,在fiddler中点击WinConfig按钮可以解除这个诅咒,这个与菜单......
  • 接口测试|Fiddler界面工具栏介绍(二)
    Fiddler界面工具栏介绍上篇文章介绍了顶部工具栏,本篇文章我们介绍底部状态栏Fiddler底端状态栏(1)黑色(控制台):可以在里面输入命令行,如输入help回车之后,在浏览器打开使用说明(2)C......
  • 接口测试|Fiddler界面工具栏介绍(三)
    Fiddler界面工具栏介绍前两篇文章我们分别介绍了顶部工具栏,底部状态栏,本篇文章我们介绍右侧高级工具栏。右侧高级工具栏(1)GetStarted:主页面(2)Statistics:请求统计视图,用来查看......
  • 软件测试常用的工具都有哪些-测试常用工具
     一、一个从事软件测试行业十年的老司机列出以下与软件测试相关的工具:1.操作系统:Linux:vmware、xshell、xftp、ssh2.数据库:主流是以下三种数据库,尤其是MySQL以及ora......
  • LocalDateTime时间工具之“2023-01-18T23:59:59.999999999”转“yyyy-MM-dd HH:mm:ss
    LocalDateTime时间工具之“2023-01-18T23:59:59.999999999”转“yyyy-MM-ddHH:mm:ss”代码LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-ddHH:m......
  • 获取指定n个工作日后的日期工具类
    importjava.text.ParseException;importjava.text.SimpleDateFormat;importjava.util.*;publicclassWeekdaysUtils{publicstaticList<String>list=newArray......