最近做业务遇到了一点麻烦,我调用某文件服务器的API返回所有文件的路径大致是如下的字符串:
achievement/image/b97fa1c05ed1e34e02285f4b05ad227e.png
achievement/image/c162db7921d20ff35f0308af2c859c90.png
channel/image/9471461ad403aa40b1ae636fc6510815.png
channel/image/98a1778ba7d65546ecd67b59ef09acf9.png
/etc/init.d/mysql/mysql
/etc/profile
/tmp/垃圾.tmp
courses/pvpjson/402806c062c415c90162d74513f40077.json
courses/pvpjson/402806c062c415c90162d74513f4007s.json
......
我需要把这些数据以树的形式展示到页面上,以便加以操作
如何把他们转换成树结构的JSON字符串呢?
如何把它们以树的结构呈现在H5的页面中呢?
下面是layui官网tree 有关的数据结构 大致是这个样子的
https://fly.layui.com/jie/19038/
[
{
title: "节点1", value: "jd1", data: [
{ title: "节点1.1", checked: true, disabled: true, value: "jd1.1", data: [] }
, { title: "节点1.2", value: "jd1.2", checked: true, data: [] }
, { title: "节点1.3", value: "jd1.3", disabled: true, data: [] }
, { title: "节点1.4", value: "jd1.4", data: [] }
]
}
, {
title: "节点2", value: "jd2", data: [
{ title: "节点2.1", value: "jd2.1", data: [] }
, { title: "节点2.2", value: "jd2.2", data: [] }
, { title: "节点2.3", value: "jd2.3", data: [] }
, { title: "节点2.4", value: "jd2.4", data: [] }
]
}
, { title: "节点3", value: "jd3", data: [] }
, { title: "节点4", value: "jd4", data: [] }
]
想了很久虽然不是很完美,算法复杂度也比较高,但还是把我大致的过程写一下:
思路:
- 将字符串进行分类
- 构造Vo对象
针对这两点 我设计了 2个实体类
package pers.zpw.TreeTest;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import java.util.Objects;
/**
* 对文件进行分类
* Created by ZhuPengWei on 2018/8/17.
*/
@Data
public class FileClassify {
/**
* composition/courses/2c918088615078af0161547c4a15006f.mp3
* <p>
* 对于composition parent为null self为composition child为courses
* 对于courses parent为composition self为courses child为2c918088615078af0161547c4a15006f.mp3
* 对于2c918088615078af0161547c4a15006f.mp3 parent为courses self为2c918088615078af0161547c4a15006f.mp3 child为null
*/
/*父*/
private String parent;
/*自己*/
private String self;
/*子*/
private String child;
/*前缀*/
private String prefix;
public FileClassify(String parent, String self, String child, String prefix) {
this.parent = parent;
this.self = self;
this.child = child;
this.prefix = prefix;
}
}
package pers.zpw.TreeTest;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* 文件树结构
* Created by ZhuPengWei on 2018/8/17.
*/
@Data
public class FileTreeVo {
private String title;
private List<FileTreeVo> data;
@Override
public String toString() {
return "FileTreeVo{" +
"title='" + title + '\'' +
", data=" + data +
'}';
}
}
下面是完整的代码
package pers.zpw.TreeTest;
import org.apache.commons.lang3.StringUtils;
import java.io.*;
import java.util.*;
import java.util.stream.Collectors;
/**
* 字符串路径转换成Tree格式
* Created by ZhuPengWei on 2018/8/17.
*/
public class StringPathToTree {
private static List<String> urlList = new ArrayList<>();
static {
try {
// url.txt存放 如最上面格式的字符串
InputStream is = new FileInputStream(new File("url.txt"));
BufferedReader br = new BufferedReader(new InputStreamReader(is));
while (true) {
String line = br.readLine();
if (line == null) {
break;
}
urlList.add(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
//文件分类后的集合
List<FileClassify> fileClassifyList = new ArrayList<>();
// 对数据进行分类
for (String url : urlList) {
String[] splitPath = url.split("/");
for (int i = 0; i < splitPath.length; i++) {
// 易得 parent,self,child 与i 的关系
String parent = i == 0 ? null : splitPath[i - 1];
String self = splitPath[i];
String child = i + 1 == splitPath.length ? null : splitPath[i + 1];
String prefix = parent == null ? "" : getPrefix(splitPath, i);
fileClassifyList.add(new FileClassify(parent, self, child, prefix));
}
}
// 筛选出parent 为null 的FileClassify集合
// 根据FileClassify的getSelf 分组
Map<String, List<FileClassify>> groupByMap = fileClassifyList.stream().filter(fileClassify -> fileClassify.getParent() == null).collect(Collectors.groupingBy(FileClassify::getSelf));
// 此时 result 就是想要的结果
List<FileTreeVo> result = getFileTreeVoList(groupByMap, fileClassifyList);
System.out.println(result);
}
/**
* 获取文件前缀
* 比如 image/12312/head.png
* head.png的前缀为 image12312
*
* @param splitPath 文件完整路径根据"/" 切割后的数组
* @param endIndex 终止索引
* @return 文件前缀
*/
private static String getPrefix(String[] splitPath, int endIndex) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < endIndex; i++) {
result.append(splitPath[i]);
}
return result.toString();
}
/**
* 获取文件Vo集合
*
* @param root 根据self分组后的 文件分类结合
* @param fileClassifyList 文件分类集合
*/
private static List<FileTreeVo> getFileTreeVoList(Map<String, List<FileClassify>> root, List<FileClassify> fileClassifyList) {
List<FileTreeVo> result = new ArrayList<>();
Set<Map.Entry<String, List<FileClassify>>> entries = root.entrySet();
for (Map.Entry<String, List<FileClassify>> entry : entries) {
FileTreeVo fileTreeVo = new FileTreeVo();
String key = entry.getKey();
fileTreeVo.setTitle(key);
List<FileClassify> list = entry.getValue();
for (FileClassify fileClassify : list) {
if (StringUtils.isNotBlank(fileClassify.getChild())) {
// 首先筛选出 父节点 为key,前缀为父节点的前缀+本身 并且 子节点 不为空 的FileClassify集合
// 然后根据子节点 对集合进行分组
Map<String, List<FileClassify>> child = fileClassifyList.stream()
.filter(e -> key.equals(e.getParent()) && e.getPrefix().equals(fileClassify.getPrefix() + fileClassify.getSelf()) && StringUtils.isNoneBlank(e.getSelf()))
.collect(Collectors.groupingBy(FileClassify::getSelf));
fileTreeVo.setData(getFileTreeVoList(child, fileClassifyList));
}
}
result.add(fileTreeVo);
}
return result;
}
}
如果有更好的解决方案请私聊我,谢谢了