引子:从一个问题开始
在日常开发中,树形结构的构建是一个常见的需求,例如分类、菜单、组织架构等场景。而随着Java版本的不断更新,一些新的特性如Java 11中的String.repeat
方法和Map.getOrDefault
方法为我们提供了更简洁、优雅的解决方案。同时,借助 Lombok 注解,我们可以进一步减少冗余代码,提升开发效率。
假设我们有一个类型表,包含以下字段:
id
: 节点唯一标识code
: 分类代码name
: 分类名称parentId
: 父节点ID(根节点为0)
我们需要根据这个表构建一个树形结构,并以缩进的形式打印出来。例如:
一级分类
二级分类
三级分类
一级分类(1)
二级分类
面对这样的需求,本文将结合 Lombok 和 Java 11的新特性,展示如何优雅地实现树结构的递归构建。
核心实现:树结构递归构建
1. 定义实体类(使用 Lombok 优化)
通过 Lombok 的 @Data
注解,我们可以自动生成 getter
、setter
和 toString
方法,从而避免手动编写这些基础代码。
import lombok.Data;
import java.util.List;
@Data // 自动生成 getter、setter 和 toString 方法
public class TreeNode {
private int id;
private String code;
private String name;
private int parentId;
private List<TreeNode> children = new ArrayList<>();
}
2. 数据准备与测试用例
模拟一个包含分类信息的列表,每个分类用 TreeNode 对象表示。
import org.junit.jupiter.api.Test;
import java.util.*;
public class TreeBuilderTest {
@Test
public void typeTree() {
List<TreeNode> list = new ArrayList<>();
list.add(new TreeNode(1, "1", "一级分类", 0));
list.add(new TreeNode(2, "2", "一级分类(1)", 0));
list.add(new TreeNode(3, "3", "二级分类", 1));
list.add(new TreeNode(4, "4", "三级分类", 3));
list.add(new TreeNode(5, "5", "二级分类", 2));
// 构建树结构
List<TreeNode> treeList = buildTree(list);
printTree(treeList, 0);
}
public List<TreeNode> buildTree(List<TreeNode> list) {
Map<Integer, List<TreeNode>> listMap = list.stream()
.collect(Collectors.groupingBy(TreeNode::getParentId));
List<TreeNode> rootList = listMap.getOrDefault(0, Collections.emptyList());
setChildren(rootList, listMap);
return rootList;
}
public void setChildren(List<TreeNode> rootList, Map<Integer, List<TreeNode>> listMap) {
rootList.forEach(root -> {
List<TreeNode> children = listMap.getOrDefault(root.getId(), Collections.emptyList());
if (!children.isEmpty()) {
root.setChildren(children);
setChildren(children, listMap);
}
});
}
public void printTree(List<TreeNode> nodes, int level) {
for (TreeNode node : nodes) {
System.out.println(" ".repeat(level * 4) + node.getName());
printTree(node.getChildren(), level + 1);
}
}
}
3. 运行结果
假设输入的数据如上所示,运行程序后输出的树结构如下:
一级分类
二级分类
三级分类
一级分类(1)
二級分类
Java 11中的String.repeat方法详解
String.repeat(int count) 是 Java 11 引入的一个新方法,用于将字符串重复指定次数。它的语法简单直观,可以显著简化代码。
示例
public class RepeatExample {
public static void main(String[] args) {
String str = "Hello";
int times = 3;
// 使用 repeat 方法
String result = str.repeat(times);
System.out.println(result); // 输出: HelloHelloHello
}
}
特点
- 避免冗余代码:无需手动拼接字符串。
- 提高可读性:代码更加简洁明了。
- 性能优化:底层实现了高效的重复操作。
Map.getOrDefault
方法详解
Map.getOrDefault(Object key, V defaultValue) 是 Map 接口提供的一个方法,用于获取指定键的值。如果键不存在,则返回默认值。
示例
Map<Integer, String> map = new HashMap<>();
map.put(1, "Value1");
// 使用 getOrDefault 方法
String value = map.getOrDefault(2, "DefaultValue");
System.out.println(value); // 输出: DefaultValue
特点
- 避免空指针异常:直接返回默认值,无需额外判断。
- 简化代码:减少了显式的
if-else
逻辑。 - 适用场景:适用于简单的键值查找场景。
总结
本文通过一个树结构递归构建的案例,详细介绍了如何结合 Lombok 和 Java 11 的新特性来优化代码:
- Lombok 的
@Data
注解:自动生成getter
、setter
和toString
方法,减少冗余代码。 - Java 11 的
String.repeat
方法:用于生成重复字符串,尤其在格式化输出时非常有用。 Map.getOrDefault
方法:适合处理可能为空的键值查找场景,简化了代码逻辑。
希望本文能为你提供一些启发,在实际开发中灵活运用这些特性,提升代码质量!如果你还有其他问题或需要进一步探讨,请随时留言交流。
感谢阅读!欢迎点赞、收藏和评论,一起学习进步!