Java實(shí)現(xiàn)樹(shù)形菜單的方法總結(jié)
當(dāng)我們想要展示層級(jí)結(jié)構(gòu),如文件目錄、組織結(jié)構(gòu)或分類(lèi)目錄時(shí),樹(shù)形菜單是一個(gè)直觀且有效的解決方案。在Java中,有多種方式可以實(shí)現(xiàn)樹(shù)形菜單,本文將介紹其中幾種常見(jiàn)方法,并配有示例代碼。
1. 使用遞歸法
遞歸法是最直觀的實(shí)現(xiàn)樹(shù)形菜單的方法。我們先定義節(jié)點(diǎn)結(jié)構(gòu),然后通過(guò)遞歸方式構(gòu)建每一個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)。
實(shí)例代碼:
class TreeNode {
int id;
int parentId;
String name;
List<TreeNode> children;
// 構(gòu)造函數(shù)、getters、setters省略
}
public List<TreeNode> buildTree(List<TreeNode> nodes, int parentId) {
List<TreeNode> tree = new ArrayList<>();
for (TreeNode node : nodes) {
if (node.parentId == parentId) {
node.children = buildTree(nodes, node.id);
tree.add(node);
}
}
return tree;
}2. 使用隊(duì)列法 (層次遍歷)
使用隊(duì)列實(shí)現(xiàn)樹(shù)形菜單可以有效減少遞歸的深度,特別是在樹(shù)形結(jié)構(gòu)很深的情況下。
實(shí)例代碼:
public List<TreeNode> buildTreeWithQueue(List<TreeNode> nodes) {
if (nodes == null || nodes.isEmpty()) {
return Collections.emptyList();
}
Map<Integer, TreeNode> nodeMap = nodes.stream().collect(Collectors.toMap(TreeNode::getId, node -> node));
List<TreeNode> tree = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<>(nodes);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
if (node.parentId == 0) {
tree.add(node);
} else {
TreeNode parent = nodeMap.get(node.parentId);
if (parent.children == null) {
parent.children = new ArrayList<>();
}
parent.children.add(node);
}
}
return tree;
}3. 使用Map索引優(yōu)化
通過(guò)使用Map進(jìn)行索引,可以提高搜索效率,特別是當(dāng)節(jié)點(diǎn)數(shù)量非常多時(shí)。
實(shí)例代碼:
public List<TreeNode> buildTreeWithMap(List<TreeNode> nodes) {
Map<Integer, List<TreeNode>> childrenMap = new HashMap<>();
List<TreeNode> rootNodes = new ArrayList<>();
for (TreeNode node : nodes) {
if (node.parentId == 0) {
rootNodes.add(node);
} else {
childrenMap
.computeIfAbsent(node.parentId, k -> new ArrayList<>())
.add(node);
}
}
for (TreeNode rootNode : rootNodes) {
rootNode.children = getChildren(rootNode.id, childrenMap);
}
return rootNodes;
}
private List<TreeNode> getChildren(int parentId, Map<Integer, List<TreeNode>> childrenMap) {
List<TreeNode> children = childrenMap.get(parentId);
if (children != null) {
for (TreeNode child : children) {
child.children = getChildren(child.id, childrenMap);
}
}
return children;
}4. 數(shù)據(jù)庫(kù)的樹(shù)形編碼的方式
步驟1: 創(chuàng)建數(shù)據(jù)庫(kù)表結(jié)構(gòu)
首先,我們需要一個(gè)數(shù)據(jù)庫(kù)表來(lái)存儲(chǔ)節(jié)點(diǎn)數(shù)據(jù):
CREATE TABLE tree_nodes (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
path VARCHAR(255) DEFAULT '',
parent_id INT
);其中,path字段用于存儲(chǔ)從根節(jié)點(diǎn)到當(dāng)前節(jié)點(diǎn)的路徑,如1/3/5/。
步驟2: Java 數(shù)據(jù)模型
我們需要一個(gè)Java類(lèi)來(lái)表示數(shù)據(jù)庫(kù)中的節(jié)點(diǎn):
public class TreeNode {
private int id;
private String name;
private String path;
private int parentId;
// Getter, Setter 和 Constructor
}步驟3: 插入節(jié)點(diǎn)
插入一個(gè)新的節(jié)點(diǎn)時(shí),我們需要計(jì)算它的路徑:
public void addNode(String name, int parentId, Connection connection) throws SQLException {
String path;
if (parentId == 0) {
path = "/";
} else {
String parentPathQuery = "SELECT path FROM tree_nodes WHERE id = ?";
try (PreparedStatement stmt = connection.prepareStatement(parentPathQuery)) {
stmt.setInt(1, parentId);
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
path = rs.getString("path") + parentId + "/";
} else {
throw new SQLException("Parent not found");
}
}
}
String insertQuery = "INSERT INTO tree_nodes (name, path, parent_id) VALUES (?, ?, ?)";
try (PreparedStatement stmt = connection.prepareStatement(insertQuery)) {
stmt.setString(1, name);
stmt.setString(2, path);
stmt.setInt(3, parentId);
stmt.executeUpdate();
}
}步驟4: 獲取某節(jié)點(diǎn)的所有子節(jié)點(diǎn)
public List<TreeNode> getChildren(int nodeId, Connection connection) throws SQLException {
List<TreeNode> children = new ArrayList<>();
String pathQuery = "SELECT path FROM tree_nodes WHERE id = ?";
String path;
try (PreparedStatement stmt = connection.prepareStatement(pathQuery)) {
stmt.setInt(1, nodeId);
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
path = rs.getString("path") + nodeId + "/";
} else {
throw new SQLException("Node not found");
}
}
String childrenQuery = "SELECT * FROM tree_nodes WHERE path LIKE ?";
try (PreparedStatement stmt = connection.prepareStatement(childrenQuery)) {
stmt.setString(1, path + "%");
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
TreeNode node = new TreeNode();
node.setId(rs.getInt("id"));
node.setName(rs.getString("name"));
node.setPath(rs.getString("path"));
node.setParentId(rs.getInt("parent_id"));
children.add(node);
}
}
return children;
}總結(jié)
以上我們介紹了三種在Java中實(shí)現(xiàn)樹(shù)形菜單的方法,從基礎(chǔ)的遞歸法、隊(duì)列法到使用Map進(jìn)行優(yōu)化。根據(jù)實(shí)際需求和數(shù)據(jù)量大小,你可以選擇合適的方法進(jìn)行實(shí)現(xiàn)。不過(guò),無(wú)論使用哪種方法,都要確保理解樹(shù)形結(jié)構(gòu)的基礎(chǔ)原理和具體實(shí)現(xiàn)細(xì)節(jié),以確保代碼的正確性和效率。 還有一種是路徑枚舉方式的一個(gè)簡(jiǎn)單例子,它已經(jīng)足夠用于實(shí)際應(yīng)用。當(dāng)然,還有許多細(xì)節(jié)可以優(yōu)化,如路徑長(zhǎng)度限制、節(jié)點(diǎn)移動(dòng)等。而其他的樹(shù)形編號(hào)方法,如嵌套集模型和閉包表,會(huì)有更復(fù)雜的邏輯。但總的來(lái)說(shuō),理解核心概念并將其應(yīng)用于實(shí)際代碼是關(guān)鍵。
到此這篇關(guān)于Java實(shí)現(xiàn)樹(shù)形菜單的方法總結(jié)的文章就介紹到這了,更多相關(guān)Java樹(shù)形菜單內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- JAVA遞歸生成樹(shù)形菜單的實(shí)現(xiàn)過(guò)程
- java實(shí)現(xiàn)樹(shù)形菜單對(duì)象
- java利用遞歸調(diào)用實(shí)現(xiàn)樹(shù)形菜單的樣式
- java編程兩種樹(shù)形菜單結(jié)構(gòu)的轉(zhuǎn)換代碼
- java實(shí)現(xiàn)遍歷樹(shù)形菜單兩種實(shí)現(xiàn)代碼分享
- java實(shí)現(xiàn)構(gòu)造無(wú)限層級(jí)樹(shù)形菜單
- Java構(gòu)建樹(shù)形菜單的實(shí)例代碼(支持多級(jí)菜單)
- Java遞歸如何正確輸出樹(shù)形菜單
相關(guān)文章
Java基于中介者模式實(shí)現(xiàn)多人聊天室功能示例
這篇文章主要介紹了Java基于中介者模式實(shí)現(xiàn)多人聊天室功能,詳細(xì)分析了中介者模式的概念、原理以及使用中介模式實(shí)現(xiàn)多人聊天的步驟、操作技巧與注意事項(xiàng),需要的朋友可以參考下2018-05-05
詳解Mybatis中的 ${} 和 #{}區(qū)別與用法
這篇文章主要介紹了Mybatis中的 ${} 和 #{}區(qū)別與用法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07
struts2 validation.xml 驗(yàn)證規(guī)則代碼解析
這篇文章主要介紹了struts2 validation.xml 驗(yàn)證規(guī)則代碼解析,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01
Mybatis-Plus自動(dòng)填充更新操作相關(guān)字段的實(shí)現(xiàn)
這篇文章主要介紹了Mybatis-Plus自動(dòng)填充更新操作相關(guān)字段的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
Java中BigDecimal類(lèi)的簡(jiǎn)單用法
這篇文章主要介紹了Java中BigDecimal類(lèi)的簡(jiǎn)單用法,是Java應(yīng)用程序開(kāi)發(fā)中非常實(shí)用的技巧,本文以實(shí)例形式對(duì)此進(jìn)行了簡(jiǎn)單的分析,需要的朋友可以參考下2014-09-09
spring mvc中的@PathVariable獲得請(qǐng)求url中的動(dòng)態(tài)參數(shù)
本文主要介紹了spring mvc中的@PathVariable獲得請(qǐng)求url中的動(dòng)態(tài)參數(shù)的代碼。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-02-02
SpringBoot同時(shí)集成Mybatis和Mybatis-plus框架
在實(shí)際開(kāi)發(fā)中,項(xiàng)目里面一般都是Mybatis和Mybatis-Plus公用,但是公用有版本不兼容的問(wèn)題,本文主要介紹了Spring Boot項(xiàng)目中同時(shí)集成Mybatis和Mybatis-plus,具有一檔的參考價(jià)值,感興趣的可以了解一下2024-12-12

