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

 更新时间:2023年08月30日 10:46:40   作者:一只爱撸猫的程序猿  
当我们想要展示层级结构,如文件目录、组织结构或分类目录时,树形菜单是一个直观且有效的解决方案,本文为大家整理了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树形菜单内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java基于中介者模式实现多人聊天室功能示例

    Java基于中介者模式实现多人聊天室功能示例

    这篇文章主要介绍了Java基于中介者模式实现多人聊天室功能,详细分析了中介者模式的概念、原理以及使用中介模式实现多人聊天的步骤、操作技巧与注意事项,需要的朋友可以参考下
    2018-05-05
  • 详解Mybatis中的 ${} 和 #{}区别与用法

    详解Mybatis中的 ${} 和 #{}区别与用法

    这篇文章主要介绍了Mybatis中的 ${} 和 #{}区别与用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • struts2 validation.xml 验证规则代码解析

    struts2 validation.xml 验证规则代码解析

    这篇文章主要介绍了struts2 validation.xml 验证规则代码解析,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01
  • Java获取当前时间年月日的方法

    Java获取当前时间年月日的方法

    这篇文章主要为大家详细介绍了Java获取当前时间年月日的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11
  • 使用log4j2关闭debug日志

    使用log4j2关闭debug日志

    这篇文章主要介绍了使用log4j2关闭debug日志方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • Mybatis-Plus自动填充更新操作相关字段的实现

    Mybatis-Plus自动填充更新操作相关字段的实现

    这篇文章主要介绍了Mybatis-Plus自动填充更新操作相关字段的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • Java中BigDecimal类的简单用法

    Java中BigDecimal类的简单用法

    这篇文章主要介绍了Java中BigDecimal类的简单用法,是Java应用程序开发中非常实用的技巧,本文以实例形式对此进行了简单的分析,需要的朋友可以参考下
    2014-09-09
  • SpringBoot中Excel处理完全指南分享

    SpringBoot中Excel处理完全指南分享

    这篇文章主要介绍了SpringBoot中Excel处理完全指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-04-04
  • spring mvc中的@PathVariable获得请求url中的动态参数

    spring mvc中的@PathVariable获得请求url中的动态参数

    本文主要介绍了spring mvc中的@PathVariable获得请求url中的动态参数的代码。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • SpringBoot同时集成Mybatis和Mybatis-plus框架

    SpringBoot同时集成Mybatis和Mybatis-plus框架

    在实际开发中,项目里面一般都是Mybatis和Mybatis-Plus公用,但是公用有版本不兼容的问题,本文主要介绍了Spring Boot项目中同时集成Mybatis和Mybatis-plus,具有一档的参考价值,感兴趣的可以了解一下
    2024-12-12

最新评论