/**
* 树
*
* @author luoyuanxiang
*/
public class TreeUtil {
/**
* 将list合成树
*
* @param list 需要合成树的List
* @param rootCheck 判断E中为根节点的条件,如:x->x.getPId()==-1L , x->x.getParentId()==null,x->x.getParentMenuId()==0
* @param parentCheck 判断E中为父节点条件,如:(x,y)->x.getId().equals(y.getPId())
* @param setSubChildren E中设置下级数据方法,如: Menu::setSubMenus
* @param <E> 泛型实体对象
* @return 合成好的树
*/
public static <E> List<E> makeTree(List<E> list, Predicate<E> rootCheck, BiFunction<E, E, Boolean> parentCheck, BiConsumer<E, List<E>> setSubChildren) {
return list.stream().filter(rootCheck).peek(x -> setSubChildren.accept(x, makeChildren(x, list, parentCheck, setSubChildren))).collect(Collectors.toList());
}
/**
* 将树打平成tree
*
* @param tree 需要打平的树
* @param getSubChildren 设置下级数据方法,如: Menu::getSubMenus,x->x.setSubMenus(null)
* @param setSubChildren 将下级数据置空方法,如: x->x.setSubMenus(null)
* @param <E> 泛型实体对象
* @return 打平后的数据
*/
public static <E> List<E> flat(List<E> tree, Function<E, List<E>> getSubChildren, Consumer<E> setSubChildren) {
List<E> res = new ArrayList<>();
forPostOrder(tree, item -> {
setSubChildren.accept(item);
res.add(item);
}, getSubChildren);
return res;
}
/**
* 前序遍历
*
* @param tree 需要遍历的树
* @param consumer 遍历后对单个元素的处理方法,如:x-> System.out.println(x)、 System.out::println打印元素
* @param setSubChildren 设置下级数据方法,如: Menu::getSubMenus,x->x.setSubMenus(null)
* @param <E> 泛型实体对象
*/
public static <E> void forPreOrder(List<E> tree, Consumer<E> consumer, Function<E, List<E>> setSubChildren) {
for (E l : tree) {
consumer.accept(l);
List<E> es = setSubChildren.apply(l);
if (es != null && !es.isEmpty()) {
forPreOrder(es, consumer, setSubChildren);
}
}
}
/**
* 层序遍历
*
* @param tree 需要遍历的树
* @param consumer 遍历后对单个元素的处理方法,如:x-> System.out.println(x)、 System.out::println打印元素
* @param setSubChildren 设置下级数据方法,如: Menu::getSubMenus,x->x.setSubMenus(null)
* @param <E> 泛型实体对象
*/
public static <E> void forLevelOrder(List<E> tree, Consumer<E> consumer, Function<E, List<E>> setSubChildren) {
Queue<E> queue = new LinkedList<>(tree);
while (!queue.isEmpty()) {
E item = queue.poll();
consumer.accept(item);
List<E> childList = setSubChildren.apply(item);
if (childList != null && !childList.isEmpty()) {
queue.addAll(childList);
}
}
}
/**
* 后序遍历
*
* @param tree 需要遍历的树
* @param consumer 遍历后对单个元素的处理方法,如:x-> System.out.println(x)、 System.out::println打印元素
* @param setSubChildren 设置下级数据方法,如: Menu::getSubMenus,x->x.setSubMenus(null)
* @param <E> 泛型实体对象
*/
public static <E> void forPostOrder(List<E> tree, Consumer<E> consumer, Function<E, List<E>> setSubChildren) {
for (E item : tree) {
List<E> childList = setSubChildren.apply(item);
if (childList != null && !childList.isEmpty()) {
forPostOrder(childList, consumer, setSubChildren);
}
consumer.accept(item);
}
}
/**
* 对树所有子节点按comparator排序
*
* @param tree 需要排序的树
* @param comparator 排序规则Comparator,如:Comparator.comparing(MenuVo::getRank)按Rank正序 ,(x,y)->y.getRank().compareTo(x.getRank()),按Rank倒序
* @param getChildren 获取下级数据方法,如:MenuVo::getSubMenus
* @param <E> 泛型实体对象
* @return 排序好的树
*/
public static <E> List<E> sort(List<E> tree, Comparator<? super E> comparator, Function<E, List<E>> getChildren) {
for (E item : tree) {
List<E> childList = getChildren.apply(item);
if (childList != null && !childList.isEmpty()) {
sort(childList, comparator, getChildren);
}
}
tree.sort(comparator);
return tree;
}
private static <E> List<E> makeChildren(E parent, List<E> allData, BiFunction<E, E, Boolean> parentCheck, BiConsumer<E, List<E>> children) {
return allData.stream().filter(x -> parentCheck.apply(parent, x)).peek(x -> children.accept(x, makeChildren(x, allData, parentCheck, children))).collect(Collectors.toList());
}
// 用例
public static void main(String[] args) {
// 树构件
List<MenuVO> menuVOList = new ArrayList<>();
menuVOList.add(new MenuVO("1", "0", "菜单1"));
menuVOList.add(new MenuVO("2", "1", "菜单2"));
menuVOList.add(new MenuVO("3", "1", "菜单3"));
menuVOList.add(new MenuVO("4", "2", "菜单4"));
menuVOList.add(new MenuVO("5", "2", "菜单5"));
menuVOList.add(new MenuVO("6", "3", "菜单6"));
menuVOList.add(new MenuVO("7", "3", "菜单7"));
menuVOList.add(new MenuVO("8", "4", "菜单8"));
menuVOList.add(new MenuVO("9", "5", "菜单9"));
menuVOList.add(new MenuVO("10", "0", "菜单10"));
List<MenuVO> tree = TreeUtil.makeTree(menuVOList, x -> "0".equals(x.getParentId()), (x, y) -> x.getId().equals(y.getParentId()), MenuVO::setSubMenus);
System.out.println(tree);
System.out.println(TreeUtil.flat(tree, MenuVO::getSubMenus, x -> x.setSubMenus(null)));
System.out.println(TreeUtil.sort(tree, Comparator.comparing(MenuVO::getName), MenuVO::getSubMenus));
TreeUtil.forPreOrder(tree, System.out::println, MenuVO::getSubMenus);
TreeUtil.forLevelOrder(tree, System.out::println, MenuVO::getSubMenus);
TreeUtil.forPostOrder(tree, System.out::println, MenuVO::getSubMenus);
}
public static class MenuVO {
private String id;
private String parentId;
private String name;
private List<MenuVO> subMenus;
public MenuVO(String id, String parentId, String name) {
this.id = id;
this.parentId = parentId;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<MenuVO> getSubMenus() {
return subMenus;
}
public void setSubMenus(List<MenuVO> subMenus) {
this.subMenus = subMenus;
}
@Override
public String toString() {
return "MenuVO{" +
"id='" + id + '\'' +
", parentId='" + parentId + '\'' +
", name='" + name + '\'' +
", subMenus=" + subMenus +
'}';
}
}
}
文章摘要
目录
沉浸式背景音
阅读主题设置
分享文章