表结构

RecursionBean
@Getter
@Setter
@ToString
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class RecursionBean<T> extends BaseVO {private T id;
private T pid;private List<? extends RecursionBean<T>> children;}
封装从服务器端返回的树形数据:RecursionItem
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class RecursionItem<T> extends RecursionBean<T> {private String name;public RecursionItem(T id, String name) {super.setId(id);this.name = name;}public RecursionItem(T id, String name, List<? extends RecursionBean<T>> children) {super.setId(id);this.name = name;super.setChildren(children);}
}
工具类
public class RecursionBeanUtil {private static <E, T extends RecursionBean<E>> List<T> getChildren(T root, List<T> list) {final List<T> res = new ArrayList<>();for (T item : list) {if (Objects.equals(item.getPid(), root.getId())) {item.setChildren(getChildren(item, list));res.add(item);}}return res;}public static <E, T extends RecursionBean<E>> List<T> getRecursionList(List<T> list) {if (CollectionUtil.isEmpty(list)) {return list;}final List<E> allList = list.stream().map(T::getId).toList();final List<E> topList = list.stream().filter(item -> item.getPid() == null).map(T::getId).toList();final List<E> parentList = list.stream().map(T::getPid).filter(itemPid -> !topList.contains(itemPid)).distinct().toList();final List<E> leafList = allList.stream().filter(id -> !topList.contains(id)).filter(id -> !parentList.contains(id)).toList();final List<T> res = new ArrayList<>();boolean topFlag = true;for (T item : list) {if (item.getPid() == null) {topFlag = false;item.setChildren(getChildren(item, list));res.add(item);}}if (!topFlag) {return res;}boolean parentFlag = true;for (T item : list) {if (parentList.contains(item.getPid()) && !leafList.contains(item.getId())) {item.setChildren(getChildren(item, list));parentFlag = false;res.add(item);}}if (!parentFlag) {return res;}for (T item : list) {if (leafList.contains(item.getId())) {item.setChildren(getChildren(item, list));res.add(item);}}return res;}
}