java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java树形菜单

Java实现树形菜单的方法总结

作者:一只爱撸猫的程序猿

当我们想要展示层级结构,如文件目录、组织结构或分类目录时,树形菜单是一个直观且有效的解决方案,本文为大家整理了java中几种常见方法,希望对大家有所帮助

当我们想要展示层级结构,如文件目录、组织结构或分类目录时,树形菜单是一个直观且有效的解决方案。在Java中,有多种方式可以实现树形菜单,本文将介绍其中几种常见方法,并配有示例代码。

1. 使用递归法

递归法是最直观的实现树形菜单的方法。我们先定义节点结构,然后通过递归方式构建每一个节点的子节点。

实例代码

class TreeNode {
    int id;
    int parentId;
    String name;
    List<TreeNode> children;
    // 构造函数、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. 使用队列法 (层次遍历)

使用队列实现树形菜单可以有效减少递归的深度,特别是在树形结构很深的情况下。

实例代码

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索引优化

通过使用Map进行索引,可以提高搜索效率,特别是当节点数量非常多时。

实例代码

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. 数据库的树形编码的方式

步骤1: 创建数据库表结构

首先,我们需要一个数据库表来存储节点数据:

CREATE TABLE tree_nodes (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    path VARCHAR(255) DEFAULT '',
    parent_id INT
);

其中,path字段用于存储从根节点到当前节点的路径,如1/3/5/

步骤2: Java 数据模型

我们需要一个Java类来表示数据库中的节点:

public class TreeNode {
    private int id;
    private String name;
    private String path;
    private int parentId;
    // Getter, Setter 和 Constructor
}

步骤3: 插入节点

插入一个新的节点时,我们需要计算它的路径:

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: 获取某节点的所有子节点

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;
}

总结

以上我们介绍了三种在Java中实现树形菜单的方法,从基础的递归法、队列法到使用Map进行优化。根据实际需求和数据量大小,你可以选择合适的方法进行实现。不过,无论使用哪种方法,都要确保理解树形结构的基础原理和具体实现细节,以确保代码的正确性和效率。 还有一种是路径枚举方式的一个简单例子,它已经足够用于实际应用。当然,还有许多细节可以优化,如路径长度限制、节点移动等。而其他的树形编号方法,如嵌套集模型和闭包表,会有更复杂的逻辑。但总的来说,理解核心概念并将其应用于实际代码是关键。

到此这篇关于Java实现树形菜单的方法总结的文章就介绍到这了,更多相关Java树形菜单内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文