此工具类支持如下功能点:
1、平级数据递归处理成树数据
2、支持设定子级集合名称
3、支持设定多个排序字段
4、支持返回某个节点下的子级集合树数据
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import java.util.Comparator;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* @author :yangwang
* @description:平级数据处理成树数据工具类
* @email 1187493980@qq.com
* shuiyuetianwy@gmaill.com
* @date :2021/12/27 16:02
*/
public class HandleToTreeUtils {
/**
* @description: 递归处理为树结构
* @author: yangwang
* @date: 2021/12/27 16:07
* @param dataArr 原始数据
* 必含字段:id-主键,parentId-父级id
* @return JSONArray 结果集
*/
public static JSONArray handleToTree(JSONArray dataArr){
JSONArray resultJson = new JSONArray();
recursionHandleToTree(resultJson,dataArr,null,null);
return resultJson;
}
/**
* @description: 递归处理为树结构
* @author: yangwang
* @date: 2021/12/27 16:07
* @param dataArr 原始数据
* 必含字段:id-主键,parentId-父级id
* @param curId 当前节点id
* @return JSONArray 结果集
*/
public static JSONArray handleToTree(JSONArray dataArr,String curId){
JSONArray resultJson = new JSONArray();
recursionHandleToTree(resultJson,dataArr,curId,null);
return resultJson;
}
/**
* @description: 递归处理为树结构
* @author: yangwang
* @date: 2021/12/27 16:07
* @param dataArr 原始数据
* 必含字段:id-主键,parentId-父级id
* @param sortObjs 排序对象
* [{"name":"","isAsc":false},{"name":""}]
* name 排序字段名称
* isAsc true-升序(默认),false-倒叙
* @return JSONArray 结果集
*
*/
public static JSONArray handleToTree(JSONArray dataArr,Object... sortObjs){
JSONArray resultJson = new JSONArray();
recursionHandleToTree(resultJson,dataArr,null,null,sortObjs);
return resultJson;
}
/**
* @description: 递归处理为树结构
* @author: yangwang
* @date: 2021/12/27 16:07
* @param dataArr 原始数据
* 必含字段:id-主键,parentId-父级id
* @param curId 当前节点id
* @param childsName 子级集合名称(默认-childs)
* @return JSONArray 结果集
*/
public static JSONArray handleToTree(JSONArray dataArr,String curId,String childsName){
JSONArray resultJson = new JSONArray();
recursionHandleToTree(resultJson,dataArr,curId,childsName);
return resultJson;
}
/**
* @description: 递归处理为树结构
* @author: yangwang
* @date: 2021/12/27 16:07
* @param dataArr 原始数据
* 必含字段:id-主键,parentId-父级id
* @param curId 当前节点id
* @param sortObjs 排序对象
* [{"name":"","isAsc":false},{"name":""}]
* name 排序字段名称
* isAsc true-升序(默认),false-倒叙
* @return JSONArray 结果集
*/
public static JSONArray handleToTree(JSONArray dataArr,String curId,Object... sortObjs){
JSONArray resultJson = new JSONArray();
recursionHandleToTree(resultJson,dataArr,curId,null,sortObjs);
return resultJson;
}
/**
* @description: 递归处理为树结构
* @author: yangwang
* @date: 2021/12/27 16:07
* @param dataArr 原始数据
* 必含字段:id-主键,parentId-父级id
* @param curId 当前节点id
* @param childsName 子级集合名称(默认-childs)
* @param sortObjs 排序对象
* [{"name":"","isAsc":false},{"name":""}]
* name 排序字段名称
* isAsc true-升序(默认),false-倒叙
* @return JSONArray 结果集
*/
public static JSONArray handleToTree(JSONArray dataArr,String curId,String childsName,Object... sortObjs){
JSONArray resultJson = new JSONArray();
recursionHandleToTree(resultJson,dataArr,curId,childsName,sortObjs);
return resultJson;
}
/**
* @description: 递归处理为树结构
* @author: yangwang
* @date: 2021/12/27 16:07
* @param resultJson 结果集
* @param dataArr 原始数据
* 必含字段:id-主键,parentId-父级id
*/
public static void handleToTree(JSONArray resultJson, JSONArray dataArr){
recursionHandleToTree(resultJson,dataArr,null,null);
}
/**
* @description: 递归处理为树结构
* @author: yangwang
* @date: 2021/12/27 16:07
* @param resultJson 结果集
* @param dataArr 原始数据
* 必含字段:id-主键,parentId-父级id
* @param curId 当前节点id
*/
public static void handleToTree(JSONArray resultJson, JSONArray dataArr,String curId){
recursionHandleToTree(resultJson,dataArr,curId,null);
}
/**
* @description: 递归处理为树结构
* @author: yangwang
* @date: 2021/12/27 16:07
* @param resultJson 结果集
* @param dataArr 原始数据
* 必含字段:id-主键,parentId-父级id
* @param sortObjs 排序对象
* [{"name":"","isAsc":false},{"name":""}]
* name 排序字段名称
* isAsc true-升序(默认),false-倒叙
*/
public static void handleToTree(JSONArray resultJson, JSONArray dataArr,Object... sortObjs){
recursionHandleToTree(resultJson,dataArr,null,null,sortObjs);
}
/**
* @description: 递归处理为树结构
* @author: yangwang
* @date: 2021/12/27 16:07
* @param resultJson 结果集
* @param dataArr 原始数据
* 必含字段:id-主键,parentId-父级id
* @param curId 当前节点id
* @param childsName 子级集合名称(默认-childs)
*/
public static void handleToTree(JSONArray resultJson, JSONArray dataArr,String curId,String childsName){
recursionHandleToTree(resultJson,dataArr,curId,childsName);
}
/**
* @description: 递归处理为树结构
* @author: yangwang
* @date: 2021/12/27 16:07
* @param resultJson 结果集
* @param dataArr 原始数据
* 必含字段:id-主键,parentId-父级id
* @param curId 当前节点id
* @param sortObjs 排序对象
* [{"name":"","isAsc":false},{"name":""}]
* name 排序字段名称
* isAsc true-升序(默认),false-倒叙
*/
public static void handleToTree(JSONArray resultJson, JSONArray dataArr,String curId,Object... sortObjs){
recursionHandleToTree(resultJson,dataArr,curId,null,sortObjs);
}
/**
* @description: 递归处理为树结构
* @author: yangwang
* @date: 2021/12/27 16:07
* @param resultJson 结果集
* @param dataArr 原始数据
* 必含字段:id-主键,parentId-父级id
* @param curId 当前节点id
* @param childsName 子级集合名称(默认-childs)
* @param sortObjs 排序对象
* [{"name":"","isAsc":false},{"name":""}]
* name 排序字段名称
* isAsc true-升序(默认),false-倒叙
*/
public static void handleToTree(JSONArray resultJson, JSONArray dataArr,String curId,String childsName,Object... sortObjs){
recursionHandleToTree(resultJson,dataArr,curId,childsName,sortObjs);
}
/**
* @description: 递归处理为树结构
* @author: yangwang
* @date: 2021/12/27 16:07
* @param resultJson 结果集
* @param dataArr 原始数据
* 必含字段:id-主键,parentId-父级id
* @param curId 节点id
* @param childsName 子级集合名称(默认-childs)
* @param sortObjs 排序对象
* [{"name":"","isAsc":false},{"name":""}]
* name 排序字段名称
* isAsc true-升序(默认),false-倒叙
*/
private static void recursionHandleToTree(JSONArray resultJson, JSONArray dataArr, String curId, String childsName,Object... sortObjs){
if((null!=dataArr)&&(0<dataArr.size())){
//按orgId筛选
if(StringUtils.isNotBlank(curId)){
//获取当前对象下子级
JSONArray childJson = dataArr.stream().filter(d -> {
if(null!=d){
JSONObject dObj = (JSONObject) d;
if((null!=dObj)&&(dObj.containsKey("id"))&&(dObj.containsKey("parentId"))&&(StringUtils.equals(dObj.getString("parentId"),curId))){
return true;
}
}
return false;
})
.sorted(new DataSortComparator(sortObjs))
.collect(Collectors.toCollection(JSONArray::new));
if((null!=childJson)&&(0<childJson.size())){
JSONObject dataObj =null;
JSONArray levelTwoJson =null;
for(Object data:childJson){
if(null != data){
dataObj = (JSONObject) data;
if((null!=dataObj)&&(dataObj.containsKey("id"))&&(StringUtils.isNotBlank(dataObj.getString("id")))){
levelTwoJson = new JSONArray();
//递归处理子级为树结构
recursionHandleToTree(levelTwoJson,dataArr,dataObj.getString("id"),childsName,sortObjs);
if((null!=levelTwoJson)&&(0<levelTwoJson.size())){
//去重排序
levelTwoJson = levelTwoJson.stream().distinct().filter(d -> {
if(null!=d){
JSONObject dObj = (JSONObject) d;
if((null!=dObj)&&(dObj.containsKey("id"))&&(StringUtils.isNotBlank(dObj.getString("id")))){
return true;
}
}
return false;
})
.sorted(new DataSortComparator(sortObjs))
.collect(Collectors.toCollection(JSONArray::new));
dataObj.put(((StringUtils.isNotBlank(childsName))?childsName:"childs"),levelTwoJson);
}else{
dataObj.put(((StringUtils.isNotBlank(childsName))?childsName:"childs"),new JSONArray());
}
//保存当前对象到结果集
resultJson.add(dataObj);
}
}
}
}
}else{
JSONObject dataObj =null;
JSONObject topObj =null;
Optional<Object> existOpt =null;
JSONArray childJson =null;
for(Object data:dataArr){
if(null != data){
dataObj = (JSONObject) data;
if((null!=dataObj)&&(dataObj.containsKey("id"))&&(StringUtils.isNotBlank(dataObj.getString("id")))){
topObj = new JSONObject();
if((dataObj.containsKey("parentId"))&&(StringUtils.isNotBlank(dataObj.getString("parentId")))){
//检索顶级组织节点
topObj = findTopOrgNode(dataArr,dataObj.getString("parentId"));
}
if((null==topObj)||(!topObj.containsKey("id"))|| (StringUtils.isBlank(topObj.getString("id")))){
topObj = dataObj;
}
if(null!=topObj){
//判断是否存在
Boolean existFlag = false;
if((null!=resultJson)&&(0<resultJson.size())){
String topOrgId = topObj.getString("id");
existOpt = resultJson.stream().filter(s -> {
if(null!=s){
JSONObject dObj = (JSONObject) s;
if((null!=dObj)&&(dObj.containsKey("id"))&&(StringUtils.isNotBlank(dObj.getString("id")))&&(StringUtils.equals(dObj.getString("id"),topOrgId))){
return true;
}
}
return false;
}).findAny();
existFlag = existOpt.isPresent();
}
if(! existFlag){
childJson = new JSONArray();
//递归处理子级为树结构
recursionHandleToTree(childJson,dataArr,topObj.getString("id"),childsName,sortObjs);
topObj.put(((StringUtils.isNotBlank(childsName))?childsName:"childs"),childJson);
resultJson.add(topObj);
}
}
}
}
}
}
}
}
/**
* @description: 检索顶级节点
* @author: yangwang
* @date: 2021/12/27 16:07
* @param dataArr 原始数据
* @param curId 当前节点id
* @return JSONObject
*/
private static JSONObject findTopOrgNode(JSONArray dataArr,String curId){
if(StringUtils.isNotBlank(curId)){
Optional<Object> parentOpt = dataArr.stream().distinct().filter(d -> {
if(null!=d){
JSONObject dObj = (JSONObject) d;
if((null!=dObj)&&(dObj.containsKey("id"))&&(StringUtils.isNotBlank(dObj.getString("id")))&&(StringUtils.equals(dObj.getString("id"),curId))){
return true;
}
}
return false;
}).findAny();
if(parentOpt.isPresent()){
JSONObject dataObj = (JSONObject) parentOpt.get();
if((null!=dataObj)&&(dataObj.containsKey("id"))&&(StringUtils.isNotBlank(dataObj.getString("id")))){
if((dataObj.containsKey("parentId"))&&(StringUtils.isNotBlank(dataObj.getString("parentId")))){
JSONObject parentObj = findTopOrgNode(dataArr,dataObj.getString("parentId"));
return (null!=parentObj)?parentObj:dataObj;
}
return dataObj;
}
}
}
return null;
}
/**
* @description: 数据排序比较器
* sortObjs 排序对象
* [{"name":"","isAsc":false},{"name":""}]
* name 排序字段名称
* isAsc true-升序(默认),false-倒叙
* @author: yangwang
* @date: 2021/12/27 17:27
*/
public static class DataSortComparator implements Comparator<Object>{
/*排序对象*/
private Object[] sortObjs;
public DataSortComparator(Object[] sortObjs){
super();
this.sortObjs = sortObjs;
}
@Override
public int compare(Object before, Object after) {
int compareInt = 0;
if((null!=sortObjs)&&(0 < sortObjs.length)&&(null!=before)&&(null!=after)){
JSONObject sortObj =null;
JSONObject objOne = null;
JSONObject objTwo = null;
for(Object obj:sortObjs){
if(null!=obj){
sortObj = (JSONObject) obj;
if((null!=sortObj)&&(sortObj.containsKey("name"))){
objOne = ((sortObj.containsKey("isAsc"))&&(!sortObj.getBoolean("isAsc")))?(JSONObject) after:(JSONObject) before;
objTwo = ((sortObj.containsKey("isAsc"))&&(!sortObj.getBoolean("isAsc")))?(JSONObject) before:(JSONObject) after;
if((objOne.containsKey(sortObj.getString("name")))&&(null != objOne.get(sortObj.getString("name")))&&(objTwo.containsKey(sortObj.getString("name")))&&(null != objTwo.get(sortObj.getString("name")))){
try {
compareInt = (new Double(objOne.getDoubleValue(sortObj.getString("name")))).compareTo(new Double(objTwo.getDoubleValue(sortObj.getString("name"))));
}catch (Exception e){
compareInt = (objOne.getString(sortObj.getString("name"))).compareTo(objTwo.getString(sortObj.getString("name")));
}
if(0 == compareInt){
continue;
}else{
return compareInt;
}
}
}
}
}
}
return compareInt;
}
}
}