Java构建树结构工具类

import java.util.ArrayList;
import java.util.List;public interface TreeUtil {/*** 节点树抽象类* @param <K> 节点ID的数据类型* @param <T> 节点的数据类型*/interface Node<K, T extends Node<K, T>> {/*** 设置当前节点的ID*/void setId(K id);/*** 获取当前节点的ID* @return 当前节点的ID*/K getId();/*** 设置当前节点的父节点ID*/void setPid(K pid);/*** 获取当前节点的父节点ID* @return 当前节点的父节点ID*/K getPid();/*** 设置当前节点所拥有的的子节点数量*/void setCount(int count);/*** 获取当前节点所拥有的的子节点数量* @return 当前节点所拥有的的子节点数量*/int getCount();/*** 设置当前节点的子节点集合* @param child 待设置的子节点集合*/void setChild(List<T> child);/*** 获取当前节点的子节点集合* @return 当前节点的子节点集合*/List<T> getChild();}/*** 构建节点树* @param src  构建树的源集合(包含所有的子父级节点)* @param root 待填充子节点的根节点*/static <I, E extends Node<I, E>> void buildTree(List<E> src, Node<I, E> root) {List<E> child = new ArrayList<>();src.removeIf(item -> {if (item.getPid().equals(root.getId())) {child.add(item);return true;}return false;});if (!child.isEmpty()) {root.setChild(child);root.setCount(child.size());child.forEach(item -> buildTree(src, item));}}/*** 构建节点树的简单方法* @param src   待组装的节点集合* @param clazz 节点的 Class 对象* @param rid   节点树中顶级节点的ID* @return 组装好的节点树*/static <M, N extends Node<M, N>> List<N> build(List<N> src, Class<N> clazz, M rid) {Node<M, N> root;try {root = clazz.newInstance();} catch (InstantiationException | IllegalAccessException e) {throw new RuntimeException(e);}root.setId(rid);buildTree(src, root);return root.getChild();}/*** 非递归方式构建节点树* 注:不要多线程调用此方法,因为不论setChild方法还是LinkedList的add方法都不保证同步* @param src  构建树的源集合(包含所有的子父级节点)* @param root 待填充子节点的根节点*/static <I, E extends Node<I, E>> List<E> buildTreeNoRecursion(List<E> src, I root) {if (root == null) {throw new IllegalArgumentException("根节点ID不能为空");}List<E> result = new LinkedList<>();Map<I, E> map = src.stream().collect(Collectors.toMap(E::getId, e -> e));for (E elem : src) {if (Objects.equals(root, elem.getPid())) {result.add(elem);} else {E e = map.get(elem.getPid());if (e == null) {continue;}List<E> child = e.getChild();if (child == null) {LinkedList<E> list = new LinkedList<>();// 这里不保证多线程的同步性,如需要可自己处理list.add(elem);e.setChild(list);} else {e.getChild().add(elem);}}}return result;}
}
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;/*** 链式构造POJO工具类*/
public class BuilderUtil<T> {private final Supplier<T> instantiate;private final List<Consumer<T>> instanceModifiers = new ArrayList<>();public BuilderUtil(Supplier<T> instantiate) {this.instantiate = instantiate;}public static <T> BuilderUtil<T> of(Supplier<T> instantiator) {return new BuilderUtil<T>(instantiator);}public <U> BuilderUtil<T> with(BiConsumer<T, U> consumer, U value) {Consumer<T> c = instance -> consumer.accept(instance, value);instanceModifiers.add(c);return this;}public T build() {T value = instantiate.get();instanceModifiers.forEach(modifier -> modifier.accept(value));instanceModifiers.clear();return value;}}
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.omega.demo.utils.BuilderUtil;
import com.omega.demo.utils.TreeUtil;import java.util.ArrayList;
import java.util.List;public class BuildTreeTest {public static void main(String[] args) {List<TreeNode> src = new ArrayList<>();src.add(BuilderUtil.of(TreeNode::new).with(TreeNode::setId, 50066159978024960L).with(TreeNode::setName, "四川省").with(TreeNode::setPid, 0L).build());src.add(BuilderUtil.of(TreeNode::new).with(TreeNode::setId, 50066159978024961L).with(TreeNode::setName, "重庆市").with(TreeNode::setPid, 0L).build());src.add(BuilderUtil.of(TreeNode::new).with(TreeNode::setId, 50066159978024962L).with(TreeNode::setName, "山西省").with(TreeNode::setPid, 0L).build());src.add(BuilderUtil.of(TreeNode::new).with(TreeNode::setId, 50066159978024963L).with(TreeNode::setName, "成都市").with(TreeNode::setPid, 50066159978024960L).build());src.add(BuilderUtil.of(TreeNode::new).with(TreeNode::setId, 50066159978024964L).with(TreeNode::setName, "成都01").with(TreeNode::setPid, 50066159978024963L).build());src.add(BuilderUtil.of(TreeNode::new).with(TreeNode::setId, 50066159978024965L).with(TreeNode::setName, "成都02").with(TreeNode::setPid, 50066159978024963L).build());src.add(BuilderUtil.of(TreeNode::new).with(TreeNode::setId, 50066159978024966L).with(TreeNode::setName, "重庆市").with(TreeNode::setPid, 50066159978024961L).build());src.add(BuilderUtil.of(TreeNode::new).with(TreeNode::setId, 50066159978024967L).with(TreeNode::setName, "重庆01").with(TreeNode::setPid, 50066159978024966L).build());src.add(BuilderUtil.of(TreeNode::new).with(TreeNode::setId, 50066159978024968L).with(TreeNode::setName, "重庆02").with(TreeNode::setPid, 50066159978024966L).build());src.add(BuilderUtil.of(TreeNode::new).with(TreeNode::setId, 50066159978024969L).with(TreeNode::setName, "太原市").with(TreeNode::setPid, 50066159978024962L).build());src.add(BuilderUtil.of(TreeNode::new).with(TreeNode::setId, 50066159978024970L).with(TreeNode::setName, "太远01").with(TreeNode::setPid, 50066159978024969L).build());src.add(BuilderUtil.of(TreeNode::new).with(TreeNode::setId, 50066159978024971L).with(TreeNode::setName, "太远02").with(TreeNode::setPid, 50066159978024969L).build());List<TreeNode> tree = TreeUtil.build(src, TreeNode.class, 0L);ObjectMapper objectMapper = new ObjectMapper();String str;try {str = objectMapper.writeValueAsString(tree);} catch (JsonProcessingException e) {throw new RuntimeException(e);}System.out.println(str);}}
[{"id":50066159978024960,"name":"四川省","pid":0,"count":1,"child":[{"id":50066159978024960,"name":"成都市","pid":50066159978024960,"count":2,"child":[{"id":50066159978024960,"name":"成都01","pid":50066159978024960,"count":0,"child":null},{"id":50066159978024970,"name":"成都02","pid":50066159978024960,"count":0,"child":null}]}]},{"id":50066159978024960,"name":"重庆市","pid":0,"count":1,"child":[{"id":50066159978024970,"name":"重庆市","pid":50066159978024960,"count":2,"child":[{"id":50066159978024970,"name":"重庆01","pid":50066159978024970,"count":0,"child":null},{"id":50066159978024970,"name":"重庆02","pid":50066159978024970,"count":0,"child":null}]}]},{"id":50066159978024960,"name":"山西省","pid":0,"count":1,"child":[{"id":50066159978024970,"name":"太原市","pid":50066159978024960,"count":2,"child":[{"id":50066159978024970,"name":"太远01","pid":50066159978024970,"count":0,"child":null},{"id":50066159978024970,"name":"太远02","pid":50066159978024970,"count":0,"child":null}]}]}
]

Java构建递归树工具类相关推荐

  1. Java 线程 - 基础及工具类 (二)

    Java 并发系列文章 Java 线程 - 并发理论基础(一) Java 线程 - 基础及工具类 (二) Java 线程 - 并发设计模式 (三) Java 线程(二) 通用的线程生命周期 Java ...

  2. java联调生成测试数据工具类

    java联调生成测试数据工具类 一.背景 二.代码 一.背景 在日常的联调中,我们经常需要准备一定数量的测试数据,用来配合前端测试.当然对于简单的数据类型完全可以通过 JDK 自带的 Random 类 ...

  3. java图片缩放工具类,一个JAVA图形缩放处置工具类

    一个JAVA图形缩放处理工具类 调用的例子 import java.io.FileOutputStream; import java.io.IOException; import javax.imag ...

  4. JAVA I/O流工具类TextFile

    JAVA I/O流工具类TextFile由广州疯狂软件java培训分享: 本文是一个TextFile类,通过这个类我们可以调用其中的方法来简化对文件的读写,这段代码的可用性比较强.这个TextFile ...

  5. java redis remove_最全的Java操作Redis的工具类

    RedisUtil 当前版本:1.1 增加更全的方法,对以前的部分方法进行了规范命名,请放心替换成新版本. 介绍 最全的Java操作Redis的工具类,使用StringRedisTemplate实现, ...

  6. java图形验证码生成工具类

    转载自   java图形验证码生成工具类 生成验证码效果       ValidateCode.java 验证码生成类 package cn.dsna.util.images; import java ...

  7. java 代理ip工具类_Java基础之java处理ip的工具类

    java处理ip的工具类,包括把long类型的Ip转为一般Ip类型.把xx.xx.xx.xx类型的转为long类型.根据掩码位获取掩码.根据 ip/掩码位 计算IP段的起始IP.根据 ip/掩码位 计 ...

  8. java练习(数组工具类的封装)[目前写过最长的代码,虽然不难]

    java练习(数组工具类的封装)[目前写过最长的代码,虽然不难] package myUtil.arrayUtil;public class ArraysUtil {/*** 升序排列一个byte数组 ...

  9. java工具类应该抛异常吗,java学习阶段一 工具类(异常)

    java学习阶段一 工具类(异常) 介绍 异常:运行期间出现的错误 背离程序本身意图的表现 基本知识 异常的分类 根类 Throwable Error 程序无法处理的错误 表示运行应用程序中教严重的问 ...

最新文章

  1. 程序员的起床动力 | 每日趣闻
  2. 如何使用LaTeX让自己不乱?
  3. mysql创建数据库并且指定utf-8编码
  4. lisp 角平分线_最佳VisualLISP及VBAforAutoCAD2000程序123例 张光斌.pdf
  5. 工作三年左右的Java程序员跟大家谈谈从业心得
  6. 第一次做开源项目,和做SAP标准开发不同的感受
  7. git ssh配置文件 服务器_git登录ssh服务器
  8. # 定义四边形_对特殊平行四边形核心梳理,拓展提升思维
  9. UVA 10391 - Compound Words
  10. C# 概念 委托和事件
  11. ubuntu linux配置bond 网卡绑定 多个bond配置多网关
  12. 2012.4.23总结
  13. mysql基础之mariadb的安装,连接,用户,密码,权限设置语句详解
  14. JavaScript中变量的类型
  15. 过采样oversampling为什么能够提高信噪比SNR呢?
  16. 贝叶斯决策论及朴素贝叶斯分类器
  17. 软件系统概要设计的三大要素
  18. HTML5期末大作业:饮食企业网站设计——饮品饮料茶(7页) HTML+CSS+JavaScript 学生DW网页设计作业成品 web课程设计网页规划与设计 HTML静态网页...
  19. 让zheng支持activiti工作流
  20. Greenplum小把戏 - 简单函数实现URL解码(URL Decode)- 同样适用于Deepgreen和PostgreSQL...

热门文章

  1. 云计算的认识和看法_请谈谈你对云计算的理解?
  2. php购物车接口,php购物车实现
  3. 中国导电油墨市场需求预测分析及投资战略研究报告2022-2028年
  4. 几个不错的国外免费虚拟主机 Free host
  5. Alpha-Beta剪枝算法在直棋中的运用
  6. 线上CPU负载过高处理
  7. 【任务栏输入法图标不见了怎么办】
  8. 八十年代的程序员们和略显悲情的故事
  9. iPhone 相机操作指南 3.0
  10. Windows10下配置JavaCup、JFlex及运行JavaCup测试用例