日?qǐng)?bào)做的地方網(wǎng)站近期發(fā)生的新聞
簡(jiǎn)介:
????????在實(shí)際開(kāi)發(fā)中,構(gòu)建樹(shù)狀層次結(jié)構(gòu)是常見(jiàn)需求,如組織架構(gòu)、目錄結(jié)構(gòu)或菜單系統(tǒng)。本教案通過(guò)解析給定的Java代碼,展示如何使用Java 8 Stream API將扁平化的菜單數(shù)據(jù)轉(zhuǎn)換為具有層級(jí)關(guān)系的樹(shù)形結(jié)構(gòu)。
1. 核心類(lèi)定義 - Menu
@Data
@NoArgsConstructor
@AllArgsConstructor
static class Menu {private Long id;private String name;private Long parentId;private List<Menu> children;
}
提示:此處定義了一個(gè)名為Menu的類(lèi),它包含了菜單項(xiàng)的基本屬性,包括ID、名稱(chēng)、父菜單ID以及一個(gè)用于存儲(chǔ)子菜單項(xiàng)的列表。
2. main方法解析及實(shí)現(xiàn)功能
輸入?yún)?shù):
- List<Menu> menus:包含所有菜單項(xiàng)的集合。
輸出結(jié)果:
- List<Menu>:一個(gè)僅包含頂級(jí)菜單項(xiàng)的列表,每個(gè)頂級(jí)菜單項(xiàng)已填充了其下級(jí)子菜單。
public static void main(String[] args) {List<Menu> menus = menusData();/*** 從菜單列表中篩選出頂級(jí)菜單,并為其添加子菜單。** @param menus 菜單列表,包含所有菜單項(xiàng)。* @return 包含所有頂級(jí)菜單的列表,其中每個(gè)頂級(jí)菜單均已包含其所有子菜單。*/List<Menu> topLevelMenus = menus.stream() // 使用流處理menus集合.filter(menu -> menu.getParentId() == 0 || menus.stream().noneMatch(other -> other.getId().equals(menu.getParentId()))) // 篩選條件:父菜單ID為0或不存在對(duì)應(yīng)父菜單的菜單項(xiàng).peek(menu -> menu.setChildren(getChildren(menu, menus))) // 為每個(gè)頂級(jí)菜單設(shè)置子菜單.collect(Collectors.toList()); // 將篩選后的頂級(jí)菜單集合轉(zhuǎn)換為L(zhǎng)ist(Menu)類(lèi)型}
?3. 輔助方法——獲取指定菜單的所有子菜單
/*** 獲取指定菜單的所有子菜單。** @param menu 指定的菜單對(duì)象,我們要查找它的子菜單。* @param menus 所有菜單的列表,從中篩選出子菜單。* @return 返回一個(gè)包含指定菜單所有子菜單的列表。這個(gè)列表中的每個(gè)菜單對(duì)象都可能包含它們自己的子菜單列表。*/private static List<Menu> getChildren(Menu menu, List<Menu> menus) {// 使用流對(duì)菜單列表進(jìn)行處理,篩選出指定菜單的子菜單return menus.stream().filter(child -> child.getParentId().equals(menu.getId())) // 篩選條件:菜單的父菜單ID與指定菜單ID匹配.peek(child -> child.setChildren(getChildren(child, menus))) // 遞歸設(shè)置每個(gè)子菜單的子菜單列表.collect(Collectors.toList()); // 收集結(jié)果,生成列表}
4. 示例數(shù)據(jù)生成方法 —— menusData()
private static List<Menu> menusData() {return Arrays.asList(new Menu(1L, "一級(jí)菜單1", 0L, null),new Menu(2L, "二級(jí)菜單1", 1L, null),new Menu(3L, "三級(jí)菜單1", 2L, null),new Menu(4L, "一級(jí)菜單2", 0L, null),new Menu(5L, "二級(jí)菜單2", 4L, null),new Menu(6L, "一級(jí)菜單3", 0L, null));
}
5.完整代碼,以及演示(TreeExample.java)
package com.tenement.auto;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class TreeExample {@Data@NoArgsConstructor@AllArgsConstructorstaticclass Menu {private Long id;private String name;private Long parentId;private List<Menu> children;}public static void main(String[] args) {List<Menu> menus = menusData();/*** 從菜單列表中篩選出頂級(jí)菜單,并為其添加子菜單。** @param menus 菜單列表,包含所有菜單項(xiàng)。* @return 包含所有頂級(jí)菜單的列表,其中每個(gè)頂級(jí)菜單均已包含其所有子菜單。*/List<Menu> topLevelMenus = menus.stream() // 使用流處理menus集合.filter(menu -> menu.getParentId() == 0 || menus.stream().noneMatch(other -> other.getId().equals(menu.getParentId()))) // 篩選條件:父菜單ID為0或不存在對(duì)應(yīng)父菜單的菜單項(xiàng).peek(menu -> menu.setChildren(getChildren(menu, menus))) // 為每個(gè)頂級(jí)菜單設(shè)置子菜單.collect(Collectors.toList()); // 將篩選后的頂級(jí)菜單集合轉(zhuǎn)換為L(zhǎng)ist(Menu)類(lèi)型}/*** 獲取指定菜單的所有子菜單。** @param menu 指定的菜單對(duì)象,我們要查找它的子菜單。* @param menus 所有菜單的列表,從中篩選出子菜單。* @return 返回一個(gè)包含指定菜單所有子菜單的列表。這個(gè)列表中的每個(gè)菜單對(duì)象都可能包含它們自己的子菜單列表。*/private static List<Menu> getChildren(Menu menu, List<Menu> menus) {// 使用流對(duì)菜單列表進(jìn)行處理,篩選出指定菜單的子菜單return menus.stream().filter(child -> child.getParentId().equals(menu.getId())) // 篩選條件:菜單的父菜單ID與指定菜單ID匹配.peek(child -> child.setChildren(getChildren(child, menus))) // 遞歸設(shè)置每個(gè)子菜單的子菜單列表.collect(Collectors.toList()); // 收集結(jié)果,生成列表}private static List<Menu> menusData() {return Arrays.asList(new Menu(1L, "一級(jí)菜單1", 0L,null),new Menu(2L, "二級(jí)菜單1", 1L,null),new Menu(3L, "三級(jí)菜單1", 2L,null),new Menu(4L, "一級(jí)菜單2", 0L,null),new Menu(5L, "二級(jí)菜單2", 4L,null),new Menu(6L, "一級(jí)菜單3", 0L,null));}}
總結(jié):該案例展示了如何利用Java 的Stream API對(duì)菜單數(shù)據(jù)進(jìn)行處理,首先篩選出頂級(jí)菜單項(xiàng),并通過(guò)遞歸方式為其添加子菜單。最后,得到了一個(gè)完整的樹(shù)形菜單結(jié)構(gòu)。?