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