充血的菜单实体类
@Data
public class Menu {
public Integer id;
public String name;
public Integer parentId;
public List<Menu> childList;
public Menu(Integer id, String name, Integer parentId) {
this.id = id;
this.name = name;
this.parentId = parentId;
this.childList = new ArrayList<>();
}
public static List<Menu> selectAll() {
return Arrays.asList(
new Menu(1, "根节点", 0),
new Menu(2, "子节点1", 1),
new Menu(3, "子节点1.1", 2),
new Menu(4, "子节点1.2", 2),
new Menu(5, "根节点1.3", 2),
new Menu(6, "根节点2", 1),
new Menu(7, "根节点2.1", 6),
new Menu(8, "根节点2.2", 6),
new Menu(9, "根节点2.2.1", 7),
new Menu(10, "根节点2.2.2", 7),
new Menu(11, "根节点3", 1),
new Menu(12, "根节点3.1", 11)
);
}
}
先做实现
public class Test {
public static void main(String[] args) {
List<Menu> menuList = Menu.selectAll();
Map<Integer, Menu> menuMap = menuList.stream().collect(Collectors.toMap(Menu::getId, menu -> menu));
menuMap.forEach((key, value) -> {
if (value.getParentId() == 0) return;
menuMap.get(value.getParentId()).getChildList().add(value);
});
Menu root = menuMap.get(1);
System.out.println(root);
}
}
封装一下,主要抽象了实体类的ID、父节点ID、子节点列表这三个字段的Getter
public class Test {
public static void main(String[] args) {
List<Menu> menuList = Menu.selectAll();
class Tree<T>{
public T parse(List<T> list, Function<T, Integer> getId, Function<T,Integer> getParentId, Function<T, Collection<T>> getChildList) {
Map<Integer, T> map = list.stream().collect(Collectors.toMap(getId, t -> t));
map.forEach((key, value) -> {
if (getParentId.apply(value) == 0) return;
getChildList.apply(map.get(getParentId.apply(value))).add(value);
});
return map.get(1);
}
}
Menu root = new Tree<Menu>().parse(menuList, Menu::getId, Menu::getParentId, Menu::getChildList);
System.out.println(root);
}
}
再封装一下,把根节点的判断条件封装了
public class Test {
public static void main(String[] args) {
List<Menu> menuList = Menu.selectAll();
class Tree<T>{
public T parse(List<T> list, Function<T, Integer> getId, Function<T,Integer> getParentId, Function<T, Collection<T>> getChildList,Function<T,Boolean> isRoot) {
AtomicReference<T> root = new AtomicReference<>();
Map<Integer, T> map = list.stream().collect(Collectors.toMap(getId, t -> t));
map.forEach((key, value) -> {
if (isRoot.apply(value)) {
root.set(value);
return;
}
getChildList.apply(map.get(getParentId.apply(value))).add(value);
});
return root.get();
}
}
Menu root = new Tree<Menu>().parse(menuList, Menu::getId, Menu::getParentId, Menu::getChildList, menu -> menu.getParentId() == 0);
System.out.println(root);
}
}
再再封装,类泛型有点大,改为方法泛型吧
public class Test {
public static void main(String[] args) {
List<Menu> menuList = Menu.selectAll();
class Tree {
public static <T> T parse(List<T> list, Function<T, Integer> getId, Function<T,Integer> getParentId, Function<T, Collection<T>> getChildList,Function<T,Boolean> isRoot) {
AtomicReference<T> root = new AtomicReference<>();
Map<Integer, T> map = list.stream().collect(Collectors.toMap(getId, t -> t));
map.forEach((key, value) -> {
if (isRoot.apply(value)) {
root.set(value);
return;
}
getChildList.apply(map.get(getParentId.apply(value))).add(value);
});
return root.get();
}
}
Menu root = Tree.parse(menuList, Menu::getId, Menu::getParentId, Menu::getChildList, menu -> menu.getParentId() == 0);
System.out.println(root);
}
}