- 案例说明
json有一个好处就是,计算机能看懂,人也能看懂。所以有时候作为数据的载体就很方便。
我有一个json格式的数据文件叫hashTagTree.json,这个文件里面存放的是一个树状的数据。
对应的单个节点的java实体如下:
public class JsonTreeNode {
private String name;
private BigDecimal value;
private List<JsonTreeNode> children;//子节点的类型是该类本身
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getValue() {
return value;
}
public void setValue(BigDecimal value) {
this.value = value;
}
public List<JsonTreeNode> getChildren() {
return children;
}
public void setChildren(List<JsonTreeNode> children) {
this.children = children;
}
}
然后通过java相应工具类,读取这个.json文件,并解析数据(为啥放入文件?因为直接放入java不太合适,一些字符串引号之类的很容易混淆视听,不易阅读代码)。
- 解决方案
提示:如果是springboot的项目,这个json文件要放入静态资源resources下面。
读取json文件内容,并直接转换成相应的对象,我这里是JsonTreeNode ,这个方法如下,jsonFile入参是文件地址,clazz是json要转化成的java实体类的class。这里用到了方法泛型,用到了Gson和JsonReader避免重复造轮子。
public static <T> T getJsonFile(String jsonFile, Class<T> clazz) throws FileNotFoundException {
Gson gson = new Gson();
JsonReader reader = new JsonReader(new FileReader(jsonFile));
T object = gson.fromJson(reader, clazz);
return object;
}
拿到这个树的java对象以后,如何进行树的遍历呢?
这里通常我们都会使用递归算法,简单讲一下递归算法的写法。
private void removeValue(JsonTreeNode node) {
if (node != null) {
node.setValue(BigDecimal.ZERO);
List<JsonTreeNode> children = node.getChildren();
if (CollectionUtils.isNotEmpty(children)) {
for (JsonTreeNode item : children) {
this.removeValue(item);
}
}
}
}
我这里是遍历所有树节点,并把所有节点的value都设置成0。
递归算法的共通点,1、必须要有结束判断(递归到什么情况结束)。这里的结束判断并不是指整个程序的结束,而是指每一层递归应该到什么时候结束。像我这里就是node是null的时候或者下面的for循环结束后,就算结束。2、必须要调用自身定义的方法,这里是指for循环中this.removeValue(item);这句。
ps:其实递归算法相当于你编写一个循环,然后让程序自己去寻找循环的结束点,很高级的方式,感觉有点像《盗梦空间》中的,一共有几层梦境,最后自己都不知道在第几层。