java转树形结构工具类详解

本文实例为大家分享了java转树形结构工具类的具体代码,供大家参考,具体内容如下

import com.alibaba.fastjson.JSON;
import lombok.Data;
import lombok.ToString;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.util.*;

/**
 * @author : liyk
 * @version 1.0
 * @date : 2020/6/9
 */
public class TreeUtil {

  /**
   * 将 List 转为树形结构
   *
   * @param origList     : 要转换的 List
   * @param idFieldName    : id字段名
   * @param parentIdFieldName : parentId 字段名
   * @param childrenFieldName : children 字段名
   * @param <T>        : 拥有父子结构的 Entity
   * @return : 树形结果
   * @throws Exception .
   */
  public static <T> List<T> convert(List<T> origList, String idFieldName,
                   String parentIdFieldName, String childrenFieldName) throws Exception {
    // 用于保存当前 id 索引的实体类
    Map<String, T> idMaps = new HashMap<>();
    // 暂存区, 用于保存没有找到父 id 的控件
    List<T> tempList = new ArrayList<>();
    List<T> result = new ArrayList<>();
    for (T entity : origList) {
      // 获取 id, parentId, children
      String id = Objects.toString(getFieldValue(entity, idFieldName), "");
      String parentId = Objects.toString(getFieldValue(entity, parentIdFieldName), "");
      if (StringUtils.isEmpty(id)) {
        throw new Exception("存在id为空的资料");
      }
      idMaps.put(id, entity);
      if (StringUtils.isEmpty(parentId)) {
        // 如果父 id 为空, 则实体类为第一层
        result.add(entity);
      } else {
        // 根据父 id 获取实体类
        T parentEntity = idMaps.get(parentId);
        if (parentEntity == null) {
          // 没找到先放入暂存区
          tempList.add(entity);
        } else {
          // 父组件判断是否存在 children, 不存在新增, 存在则直接假如
          setChildrenValue(childrenFieldName, entity, parentEntity);
        }
      }
    }
    // 处理暂存区, 暂存区的一定不为根节点, 所以它只要父节点存在, 那么此轮查询一定能找到父节点(上一轮已经将全部节点放入 idMaps)
    for (T entity : tempList) {
      // 获取 parentId
      String parentId = Objects.toString(getFieldValue(entity, parentIdFieldName), "");
      // 根据父id获取实体类
      T parentEntity = idMaps.get(parentId);
      if (parentEntity == null) {
        throw new Exception("存在孤立的子节点");
      } else {
        // 父组件判断是否存在children, 不存在新增, 存在则直接假如
        setChildrenValue(childrenFieldName, entity, parentEntity);
      }
    }
    return result;
  }

  private static <T> void setChildrenValue(String childrenFieldName, T entity, T parentEntity) throws Exception {
    Object children = getFieldValue(parentEntity, childrenFieldName);
    List<T> childrenList;
    if (children == null) {
      childrenList = new ArrayList<>();
      childrenList.add(entity);
      setFieldValue(parentEntity, childrenFieldName, childrenList);
    } else {
      List<T> childrenReal = (List<T>) children;
      childrenReal.add(entity);
    }
  }

  private static <T> Object getFieldValue(T entity, String fieldName) throws Exception {
    Field field = ReflectionUtils.findField(entity.getClass(), fieldName);
    if (field == null) {
      throw new Exception(String.format("字段名称[%s]不存在", fieldName));
    }
    boolean accessible = field.isAccessible();
    field.setAccessible(true);
    Object result = ReflectionUtils.getField(field, entity);
    field.setAccessible(accessible);
    return result;
  }

  private static <T> void setFieldValue(T entity, String fieldName, Object value) throws Exception {
    Field field = ReflectionUtils.findField(entity.getClass(), fieldName);
    if (field == null) {
      throw new Exception(String.format("字段名称[%s]不存在", fieldName));
    }
    boolean accessible = field.isAccessible();
    field.setAccessible(true);
    ReflectionUtils.setField(field, entity, value);
    field.setAccessible(accessible);
  }

  public static void main(String[] args) throws Exception {
    List<Demo> list = new ArrayList<>();
    for (int i = 0; i < 5; i++) {
      Demo demo = new Demo(i, "一级节点" + i);
      list.add(demo);
    }
    for (int i = 5; i < 15; i++) {
      Demo demo = new Demo(i, i % 5, "二级节点" + i);
      list.add(demo);
    }
    for (int i = 15; i < 100; i++) {
      Demo demo = new Demo(i, i % 10 + 5, "三级节点" + i);
      list.add(demo);
    }
    Demo demo = new Demo(100, 102, "非法节点");
    list.add(demo);
    List<Demo> convert = TreeUtil.convert(list, "id", "pid", "children");
    String s = JSON.toJSONString(convert);
    System.out.println(s);
  }

}

@Data
@ToString
class Demo {
  private Integer id;
  private Integer pid;
  private String name;
  private List<Demo> children;

  public Demo(Integer id, Integer pid, String name) {
    this.id = id;
    this.pid = pid;
    this.name = name;
  }

  public Demo(Integer id, String name) {
    this.id = id;
    this.name = name;
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

时间: 2020-08-25

Java创建树形结构算法实例代码

在JavaWeb的相关开发中经常会涉及到多级菜单的展示,为了方便菜单的管理需要使用数据库进行支持,本例采用相关算法讲数据库中的条形记录进行相关组装和排序讲菜单组装成树形结构. 首先是需要的JavaBean import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; import j

使用递归删除树形结构的所有子节点(java和mysql实现)

1.业务场景 有如下树形结构: +-0 +-1 +-2 +-4 +-5 +-3 如果删除某个父节点,则其子节点,以及其子节点的子节点,以此类推,需要全部删除. 2.Java实现 使用Map存储树形结构的数据,id为map的key,pid为树形结构的value. import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.uti

java、js中实现无限层级的树形结构方法(类似递归)

js中: var zNodes=[ {id:0,pId:-1,name:"Aaaa"}, {id:1,pId:0,name:"A"}, {id:11,pId:1,name:"A1"}, {id:12,pId:1,name:"A2"}, {id:13,pId:1,name:"A3"}, {id:2,pId:0,name:"B"}, {id:21,pId:2,name:"B1&qu

Java递归遍历树形结构

废话不多说了,直接给大家贴代码,具体代码如下所示: //菜单树形结构 public JSONArray treeMenuList(JSONArray menuList, int parentId) { JSONArray childMenu = new JSONArray(); for (Object object : menuList) { JSONObject jsonMenu = JSONObject.fromObject(object); int menuId = jsonMenu.ge

使用递归算法结合数据库解析成Java树形结构的代码解析

1.准备表结构及对应的表数据 a.表结构: create table TB_TREE ( CID NUMBER not null, CNAME VARCHAR2(50), PID NUMBER //父节点 ) b.表数据: insert into tb_tree (CID, CNAME, PID) values (1, '中国', 0); insert into tb_tree (CID, CNAME, PID) values (2, '北京市', 1); insert into tb_tree

Java遍历输出指定目录、树形结构所有文件包括子目录下的文件

下面通过一段代码介绍下Java输出指定目录.树形结构下的所有文件包括子目录中的文件的方法,并附有效果图. import java.io.File; public class ReadDirectory { // 文件所在的层数 private int fileLevel; /** * 生成输出格式 * @param name 输出的文件名或目录名 * @param level 输出的文件名或者目录名所在的层次 * @return 输出的字符串 */ public String createPri

Java数据封装树形结构代码实例

这篇文章主要介绍了Java数据封装树形结构代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.实体类 @data public class PublishServiceType implements Comparable<PublishServiceType>{ /** * */ private static final long serialVersionUID = -3572108154932898825L; /* * @see

解决java idea新建子目录时命名不是树形结构的问题

问题再现 解决办法:点击设置,然后再点击Compact Middle Packages,如下图: 成功 补充知识:idea 2019.2 svn 忽略文件/目录 .idea *.iml target log 背景 idea 2019.2 不再支持忽略 svn 文件和目录的功能,我们可以使用小乌龟自带的功能来解决这个问题. 1. 在项目根目录的空白处,点击右键菜单 TortoiseSVN->Properties 2. New->Other 3. 选择svn:global-ignores 所有子目

JSON复杂数据处理之Json树形结构数据转Java对象并存储到数据库的实现

在网站开发中经常遇到级联数据的展示,比如选择城市的时候弹出的省市县选择界面.很多前端制作人员习惯于从JSON中而不是从数据库中获取省市县数据.那么在选择了省市县中的某一个城市 ,存储到数据库中需要存储所选城市的代码.所以需要一个能将JSON数据(一般存储在javascript脚本中)结构全部导入到数据库中的功能. JSON的特点是支持层级结构.支持数组表示的对象 .下面的示例介绍如何将JSON的省市县数据保存到数据库中,实现原理非常简单,就是利用JSON的java工具包API,将层次结构的JSO

json+jQuery实现的无限级树形菜单效果代码

本文实例讲述了json+jQuery实现的无限级树形菜单效果代码.分享给大家供大家参考.具体如下: 这里演示json树形菜单,JS无级树树形菜单,引入了jQuery插件,使用递归实现获取无级树数据并生成DOM结构,可以在JSON数据里 扩展无限级 看结构就明白. 先来看看运行效果截图: 在线演示地址如下: http://demo.jb51.net/js/2015/jquery-json-tree-style-menu-codes/ 具体代码如下: <!DOCTYPE html PUBLIC &quo

ajax请求后台得到json数据后动态生成树形下拉框的方法

如下所示: <select id="cc" class="easyui-combotree" style="width:580px;" name="rempId" data-options="required:true"></select> <script> $(function(){ $.ajax({ url:"departmentAction_getAllD

VBScript把json字符串解析成json对象的2个方法

asp/vbscript将json字符解析为json对象的方法,如果asp使用jscript来编写服务器端代码操作json字符串就简单了,vbscript需要MSScriptControl.ScriptControl或者服务器端的jscript来作为中间体才行. vbscript将json字符解析为json对象的方法一 使用MSScriptControl.ScriptControl组件,请用IE浏览器运行本示例,会有安全提示,需要点击"是"允许创建. MSScriptControl.S

jQuery Ajax和getJSON获取后台普通json数据和层级json数据用法分析

本文实例讲述了jQuery Ajax和getJSON获取后台普通json数据和层级json数据用法.分享给大家供大家参考,具体如下: 运行效果截图如下: 具体代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="h

java对象序列化与反序列化的默认格式和json格式使用示例

默认格式 复制代码 代码如下: public class MyClass implements Serializable{...} 序列化: 复制代码 代码如下: ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream(outputPath)); output.writeObject(myObject); 反序列化: 复制代码 代码如下: ObjectInputStream input = new Objec

谈谈JSON对象和字符串之间的相互转换JSON.stringify(obj)和JSON.parse(string)

在Firefox,chrome,opera,safari,ie9,ie8等高级浏览器直接可以用JSON对象的stringify()和parse()方法. JSON.stringify(obj)将JSON转为字符串.JSON.parse(string)将字符串转为JSON格式: var a={"name":"tom","sex":"男","age":"24"}; var aToStr =

JAVA对象JSON数据互相转换的四种常见情况

1. 把java 对象列表转换为json对象数组,并转为字符串 复制代码 代码如下: JSONArray array = JSONArray.fromObject(userlist);     String jsonstr = array.toString(); 2.把java对象转换成json对象,并转化为字符串 复制代码 代码如下: JSONObject object = JSONObject.fromObject(invite);    String str=object.toString

基于JSON和java对象的互转方法

先说下我自己的理解,一般而言,JSON字符串要转为java对象需要自己写一个跟JSON一模一样的实体类bean,然后用bean.class作为参数传给对应的方法,实现转化成功. 上述这种方法太麻烦了.其实有一种东西叫jsonObject可以直接不用新建实体类bean,而实现转化,先说org.json.JSONObject这个JSONObject,贴上代码: import java.beans.IntrospectionException; import java.beans.Introspect

java对象与json对象之间互相转换实现方法示例

本文实例讲述了java对象与json对象之间互相转换实现方法.分享给大家供大家参考,具体如下: import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import net.sf.json.JSONArray; import net.sf.json.JSONObject; public class MainClass { public st