list转tree 工具类分享
学习使用java Function函数式编程抽象方法,以下是代码
TreeUtil.java工具类代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28import org.apache.commons.collections.CollectionUtils;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
public class TreeUtil {
/**
* 树转平铺
*
* 示例
* treeToListDeep(TreeVOs, result, TreeVO::getChildren(), l -> true);
*
* @param source 源数据
* @param target 目标容器
* @param childListFn 递归调用方法
* @param addTargetCondition 添加到容器的判断方法
*/
public static <F> void treeToListDeep(List<F> source, List<F> target, Function<F, List<F>> childListFn, Predicate<F> addTargetCondition) {
loopTree(source, childListFn, l -> {
if (addTargetCondition.test(l)) {
target.add(l);
}
});
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75/**
* 列表组装成树
*
* 示例
* List<TreeVO> treeList = listToTree(list, TreeVO::setChildren, TreeVO::getId, TreeVO::getPid, (l) -> l.getPid() == null);
*
* @param source 源数据
* @param setChildListFn 设置递归的方法
* @param idFn 获取id的方法
* @param pidFn 获取父id的方法
* @param getRootCondition 获取根节点
* @return {@link List<F>}
*/
public static <F, T> List<F> listToTree(List<F> source, BiConsumer<F, List<F>> setChildListFn, Function<F, T> idFn, Function<F, T> pidFn, Predicate<F> getRootCondition) {
return listToTree(source, setChildListFn, idFn, pidFn, getRootCondition, null);
}
/**
* 列表组装成树 (可带回调函数 idx层级 0开始)
*
* @param listen 回调函数
*/
public static <F, T> List<F> listToTree(List<F> source, BiConsumer<F, List<F>> setChildListFn, Function<F, T> idFn, Function<F, T> pidFn, Predicate<F> getRootCondition, BiConsumer<Integer, F> listen) {
List<F> tree = new ArrayList<>();
Map<T, List<F>> map = new HashMap<>(source.size());
for (F f : source) {
if (getRootCondition.test(f)) {
tree.add(f);
} else {
List<F> tempList = map.getOrDefault(pidFn.apply(f), new ArrayList<>());
tempList.add(f);
map.put(pidFn.apply(f), tempList);
}
}
tree.forEach(l -> assembleTree(l, map, setChildListFn, idFn, listen, 0));
return tree;
}
/**
* 组装树
*
*/
private static <F, T> void assembleTree(F current, Map<T, List<F>> map, BiConsumer<F, List<F>> setChildListFn, Function<F, T> idFn, BiConsumer<Integer, F> listen, int idx) {
List<F> fs = map.get(idFn.apply(current));
setChildListFn.accept(current, fs);
if (CollectionUtils.isNotEmpty(fs)) {
fs.forEach(l -> assembleTree(l, map, setChildListFn, idFn, listen, idx + 1));
}
if (listen != null) {
listen.accept(idx, current);
}
}
/**
* 递归树
*
* @param source 源数据
* @param childListFn get方法
* @param listen 回调函数
*/
public static <F> void loopTree(List<F> source, Function<F, List<F>> childListFn, Consumer<F> listen) {
loopTree(source, childListFn, listen, null);
}
public static <F> void loopTree(List<F> source, Function<F, List<F>> childListFn, Consumer<F> preListen, Consumer<F> postFun) {
if (CollectionUtils.isEmpty(source)) {
return;
}
source.forEach(l -> {
Optional.ofNullable(preListen).ifPresent(s -> s.accept(l));
loopTree(childListFn.apply(l), childListFn, preListen, postFun);
Optional.ofNullable(postFun).ifPresent(s -> s.accept(l));
});
}
}TreeUtilTest.java测试类代码(使用示例)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.ArrayList;
import java.util.List;
/**
* @author yinshuang
* @date 2022/1/20 9:18
* @description TreeUtilTest
* @copyright(c) chinacscs all rights reserved
*/
public class TreeUtilTest {
// @JsonInclude(JsonInclude.Include.NON_EMPTY)
static class TreeVO {
/**
* 节点id
*/
private Integer id;
/**
* 节点标题
*/
private String title;
/**
* 父节点id
*/
private Integer pid;
/**
* 子层级
*/
private List<TreeVO> children;
}
public void testListToTree() {
System.out.println("\n\n**********************************************组装前*******************************************\n\n");
List<TreeVO> list = new ArrayList<TreeVO>() {{
add(TreeVO.builder().id(310000).title("上海市").build());
add(TreeVO.builder().id(310101).title("黄浦区").pid(310000).build());
add(TreeVO.builder().id(310104).title("徐汇区").pid(310000).build());
add(TreeVO.builder().id(310105).title("长宁区").pid(310000).build());
add(TreeVO.builder().id(310106).title("静安区").pid(310000).build());
add(TreeVO.builder().id(310107).title("普陀区").pid(310000).build());
add(TreeVO.builder().id(310109).title("虹口区").pid(310000).build());
add(TreeVO.builder().id(420000).title("湖北省").build());
add(TreeVO.builder().id(420100).title("武汉市").pid(420000).build());
add(TreeVO.builder().id(420102).title("江岸区").pid(420100).build());
add(TreeVO.builder().id(420103).title("江汉区").pid(420100).build());
add(TreeVO.builder().id(420104).title("硚口区").pid(420100).build());
add(TreeVO.builder().id(420105).title("汉阳区").pid(420100).build());
add(TreeVO.builder().id(420106).title("武昌区").pid(420100).build());
add(TreeVO.builder().id(420107).title("青山区").pid(420100).build());
add(TreeVO.builder().id(440000).title("广东省").build());
add(TreeVO.builder().id(440100).title("广州市").pid(440000).build());
add(TreeVO.builder().id(440103).title("荔湾区").pid(440100).build());
add(TreeVO.builder().id(440104).title("越秀区").pid(440100).build());
add(TreeVO.builder().id(440105).title("海珠区").pid(440100).build());
add(TreeVO.builder().id(440106).title("天河区").pid(440100).build());
}};
//System.out.println(list.toString());
String listJson = JSONArray.toJSONString(list, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue);
System.out.println(listJson);
System.out.println("\n\n**********************************************组装后*******************************************\n\n");
List<TreeVO> tree = TreeUtil.listToTree(list, TreeVO::setChildren, TreeVO::getId, TreeVO::getPid, l -> l.getPid() == null);
//System.out.println(treeResult.toString());
String treeJson = JSONArray.toJSONString(tree, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue);
System.out.println(treeJson);
System.out.println("\n\n**********************************************平铺后*******************************************\n\n");
List<TreeVO> listDeep = new ArrayList<>();
TreeUtil.treeToListDeep(tree, listDeep, TreeVO::getChildren, l -> l.getTitle() != null);
String listDeepJson = JSONArray.toJSONString(listDeep, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue);
System.out.println(listDeep.toString());
//System.out.println(listDeepJson);
System.out.println("\n\n**********************************************结束*******************************************\n\n");
}
}
- 本文作者: yinshuang
- 本文链接: https://yinshuang007.github.io/2023/02/05/TreeUtil组装树工具类分享/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!