前言:如果字段与demo完全不同,且无法修改为demo中的匹配字段,只需修改以下部分即可
一、修改排序字段
将TreeNodes
类的"level"
改为相应的字段
如private final static String LEVEL= "level";
–>private final static String LEVEL= "myLevel";
。
若已实现排序,亦可将Tools
类里Collections.sort(treeNodes);//排序
代码注释,位置在50~60行之前
二、自定义树包含的字段
对changeKey对象进行扩展,可以为树添加更多的字段
三、自定义子树名称、ID及父ID
- 引入jar包
maven项目导入jar包
非maven项目请手动下载指定的包,并导入项目内
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
- 测试菜单列表
package ac.cn.chm.base.entity;
import lombok.Data;
@Data//或手动创建getter、setter方法
public class Menu {
private String menuId;
private String menuName;
private Integer menuLevel;
private String parentId;
private String menuIcon;
public Menu(String menuId, String menuName, Integer menuLevel, String parentId, String menuIcon) {
this.menuId = menuId;
this.menuName = menuName;
this.menuLevel = menuLevel;
this.parentId = parentId;
this.menuIcon = menuIcon;
}
}
- 通用校验接口
import java.util.Collection;
import java.util.Map;
public class CheckUtils {
public static void main(String[] args) {
double[] a = new double[0];
System.out.println(isEmpty(a));
// System.out.println("list="+isEmpty(new ArrayList<String>()));
// System.out.println("list="+isEmpty(new HashSet<String>()));
}
public static boolean isEmpty(Object o) {
if (o == null) {
return true;
} else {
if (o instanceof String && o.toString().trim().equals("")) { //字符串判断
return true;
} else if (o instanceof Iterable && ((Collection) o).size() <= 0) { //判断set和list
return true;
} else if (o instanceof Map && ((Map) o).size() == 0) { //map判断
return true;
} else if (o instanceof Object[] && ((Object[]) ((Object[]) o)).length == 0) {//object判断
return true;
} else if (isEmptyBasicDataArray(o)) { //基础数据类型数组判断
return true;
}
return false;
}
}
/**
* 判断传入所有可变参数是否有一个为空
* @param o
* @return
*/
public static boolean isOneEmpty(Object ... o){
for (Object obj :o ) {
if(isEmpty(obj)){//有一个为空,符合条件
return true;
}
}
return false;
}
/**
* 判断传入所有可变参数是否都为空
* @param o
* @return
*/
public static boolean isAllEmpty(Object ... o){
for (Object obj :o ) {
if(!isEmpty(obj)){//有一个不为空,则不符合条件
return false;
}
}
return true;
}
/**
* 判断传入可变参数是否有一个参数不为空
* @param o
* @return
*/
public static boolean isOneNotEmpty(Object ... o){
for (Object obj :o ) {
if(!isEmpty(obj)){//有一个不为空,符合条件
return true;
}
}
return false;
}
/**
* 判断传入所有可变参数是否都非空
* @param o
* @return
*/
public static boolean isAllNotEmpty(Object ... o){
for (Object obj :o ) {
if(isEmpty(obj)){//有一个为空,则不符合条件
return false;
}
}
return true;
}
/**
* 判断基础数据类型是否非空
* @param o
* @return
*/
public static boolean isNotEmpty(Object o ){
return !isEmpty(o);
}
/**
* 校验基础数据类型数组是否为空
*
* @param o
* @return
*/
public static boolean isEmptyBasicDataArray(Object o) {
if (o == null) {
return true;
} else {
if (o instanceof int[] && ((int[]) ((int[]) o)).length == 0) {
return true;
} else if (o instanceof long[] && ((long[]) ((long[]) o)).length == 0) {
return true;
} else if (o instanceof byte[] && ((byte[]) ((byte[]) o)).length == 0) {
return true;
} else if (o instanceof char[] && ((char[]) ((char[]) o)).length == 0) {
return true;
} else if (o instanceof double[] && ((double[]) ((double[]) o)).length == 0) {
return true;
} else if (o instanceof float[] && ((float[]) ((float[]) o)).length == 0) {
return true;
} else if (o instanceof short[] && ((short[]) ((short[]) o)).length == 0) {
return true;
} else if (o instanceof boolean[] && ((boolean[]) ((boolean[]) o)).length == 0) {
return true;
}
}
return false;
}
/**
* 判断基础数据类型数组是否非空
* @param o
* @return
*/
public static boolean isNotEmptyBasicDataArray(Object o){
return !isEmptyBasicDataArray(o);
}
/**
* 判断传入可变数组是否有一个为空
* @param o
* @return
*/
public static boolean isOneEmptyBasicDataArray(Object ... o){
for (Object obj :o ) {
if(isEmptyBasicDataArray(obj)){//有一个符合条件即可
return true;
}
}
return false;
}
/**
* 判断传入可变数组是否有一个非空
* @param o
* @return
*/
public static boolean isOneNotEmptyBasicDataArray(Object ... o){
for (Object obj :o ) {
if(!isEmptyBasicDataArray(obj)){//有一个符合条件即可
return true;
}
}
return false;
}
/**
* 判断传入可变数组是否全部为空
* @param o
* @return
*/
public static boolean isAllEmptyBasicDataArray(Object ... o){
for (Object obj :o ) {
if(!isEmptyBasicDataArray(obj)){//有一个不为空,则不符合条件
return false;
}
}
return true;
}
/**
* 判断传入可变数组是否全部为空
* @param o
* @return
*/
public static boolean isAllNotEmptyBasicDataArray(Object ... o){
for (Object obj :o ) {
if(isEmptyBasicDataArray(obj)){//有一个不为空,则不符合条件
return false;
}
}
return true;
}
}
- 创建TreeNodes实体类
import ac.cn.chm.tools.CheckUtils;
import com.alibaba.druid.sql.visitor.functions.Char;
import lombok.Data;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@Data
public class TreeNodes extends HashMap implements Comparable<TreeNodes> {//实现Comparable接口,实现根据level排序
public final static String LEVEL= "level"; //节点的层级 必须字段
public final static String CHILDREN ="children"; //子树 必须字段
public final static String ID = "id"; //节点的ID 必须字段
public final static String PID = "pId"; //节点的父ID 必须字段
public final static String ICON = "icon"; //节点图标 非必须
public final static String NAME = "name"; //节点名称 非必须
public TreeNodes(){
this.put("children",new ArrayList<TreeNodes>());//保存子树
}
public Integer getInt(String key){
Object o = this.get(key);
if (o instanceof Integer ||o instanceof Short ||o instanceof Long ||o instanceof Byte) {
return (Integer)o;
}else{
try{
return Integer.valueOf((String)o);
}catch (Exception e){
System.out.println("level字段无法转换为整型数字");
}
}
return 1;//不会到这来,会先抛出异常
}
public String getStr(String key){
Object o = this.get(key);
if (o instanceof Integer ||o instanceof Short ||o instanceof Long ||o instanceof Byte) {
return String.valueOf(o);
}else{
return (String)o;
}
}
@Override
public int compareTo(TreeNodes tn) {
//如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
//1排在当前的后面//-1排在当前的前面
int big = 1, small = -1, eq = 0;
if(CheckUtils.isEmpty(tn)){
return big;
}
Integer thisLevel = this.getInt(LEVEL);
Integer tnLevel = tn.getInt(LEVEL);
if (CheckUtils.isEmpty(tnLevel)) {
return big;
} else if (CheckUtils.isEmpty(thisLevel)) {
return small;
} else if (tnLevel < thisLevel) {
return big;
} else if (tnLevel > thisLevel) {
return small;
}
return eq;
}
}
- 转接类的编写
public class Tools {
public static void main(String[] args) {//测试用例
Map<String,String> changeKey = new HashMap<>();
{//必须字段
changeKey.put("menuId", TreeNodes.ID);//将“menuId”转换为TreeNodes.ID
changeKey.put("menuLevel", TreeNodes.LEVEL);
changeKey.put("parentId", TreeNodes.PID);
}
{//非必须字段
changeKey.put("menuName", TreeNodes.NAME);
changeKey.put("menuIcon", TreeNodes.ICON);
}
//可自定义更多字段
List<Menu> pts = getMenuList();//模拟获取列表信息
List<TreeNodes> list = Tools.formatTree(pts, changeKey);//将列表转换为树
System.out.println(JSON.toJSONString(list));
}
public static List<Menu> getMenuList(){
List<Menu> list = new ArrayList<>();
list.add(new Menu("1","基础管理",1,"0","base-icon"));
list.add(new Menu("2","用户管理",2,"1","user-icon"));
list.add(new Menu("6","添加菜单",3,"3","menu-add-icon"));
list.add(new Menu("7","编辑菜单",3,"3","menu-edit-icon"));
list.add(new Menu("3","菜单管理",2,"1","menu-icon"));
list.add(new Menu("4","添加用户",3,"2","user-add-icon"));
list.add(new Menu("8","添加用户并分配菜单",4,"4","user-menu-add-icon"));
list.add(new Menu("5","编辑用户",3,"2","user-edit-icon"));
return list;
}
/**
* @param list 树的内容,需要按照level从小到大进行排序,否则无法获取到第一个层级,且易造成树的分支丢失
* @param keys
* @param <T>
* @return
*/
public static <T> List<TreeNodes> formatTree(List<T> list, Map<String,String> keys) {
if (list == null || list.size() <= 0) {
return new ArrayList<>();
}
//List<TreeNodes> treeNodes = getTreeNodes(list,keys);//保存多余的字段
List<TreeNodes> treeNodes = getTreeNodesByMap(list,keys);//不保存多余的字段
Collections.sort(treeNodes);//排序
Map<String, List<TreeNodes>> map = new HashMap<>();//change,修改List为指定的类型
//转换字段
List<TreeNodes> root = null;//根目录 //change,修改List为指定的类型
for (TreeNodes current : treeNodes) {//change,修改List为指定的类型
{//添加当前元素到指定级别
String level = current.getStr(TreeNodes.LEVEL);//change,修改获取层级的方法
if (!map.containsKey(level)) {//不存在,先添加list
map.put(level, new ArrayList<TreeNodes>());//change,修改List为指定的类型
}
List<TreeNodes> arr = map.get(level);//当前层级//change,修改List为指定的类型
arr.add(current);
if (root == null) {//表示是第一级
root = arr;
}
}
//将当前元素添加到父级的子元素列表里
{
List<TreeNodes> parentTree = map.get(String.valueOf(current.getInt(TreeNodes.LEVEL) - 1));//change,修改List、获取层级的方法
if (parentTree == null) {
continue;
}
for (TreeNodes parent : parentTree) {//change,修改List为指定的类型
if (parent.get(TreeNodes.ID).equals(current.get(TreeNodes.PID))) {//如果找不到父级,则为异常数据,抛弃 //change,修改上下级关联的判断依据
((List<TreeNodes>)parent.get(TreeNodes.CHILDREN)).add(current);
break;
}
}
}
}
return root;
}
/**
* 更新字段
*/
public static String changeKey(String json, Map<String,String> keys) {
if (CheckUtils.isOneEmpty(json,keys)) {
return "";
}
for (Map.Entry<String,String> entry : keys.entrySet()) {
json = json.replaceAll(entry.getKey(),entry.getValue());
}
return json;
}
/**
* 获取TreeNodes,不去除多余字段
*/
public static <T> List<TreeNodes> getTreeNodes(List<T> list, Map<String,String> keys) {
String jsonStr = JSON.toJSONString(list);
jsonStr = changeKey(jsonStr, keys);//change,不改变格式,不需要这段代码,直接删除
List<TreeNodes> treeNodes = listClone(jsonStr, TreeNodes.class);//change,不改变格式,不需要这段代码,直接删除
return treeNodes;
}
/**
* 根据keys里的字段获取TreeNodes
*/
public static <T> List<TreeNodes> getTreeNodesByMap(List<T> list,Map<String,String> keys){
if (CheckUtils.isOneEmpty(list,keys)) {
return null;
}
String json = JSON.toJSONString(list);
List<JSONObject> objects = listClone(list,JSONObject.class);
List<TreeNodes> nodes = new ArrayList<>();
for (JSONObject t: objects ) {
for (Map.Entry<String,String> entry : keys.entrySet()) {
TreeNodes treeNodes = new TreeNodes();
treeNodes.put(entry.getValue(),t.get(entry.getKey()));
nodes.add(treeNodes);
}
}
return nodes;
}
/**
* 将一个对象的列表转换为另一个对象的列表
*
* @param k
* @param clazz
* @param <T>
* @param <K>
* @return
*/
public static <T, K> List<T> listClone(List<K> k, Class<T> clazz) {
List<T> list = JSONArray.parseArray((JSONArray.toJSON(k)).toString(), clazz);
return list;
}
/**
* 将json格式的字符串转换为指定对象的列表
*
* @param str
* @param clazz
* @param <T>
* @return
*/
public static <T> List<T> listClone(String str, Class<T> clazz) {
List<T> list = JSONArray.parseArray(str, clazz);
return list;
}
}
- 运行结果
[{
"level": 1,
"icon": "base-icon",
"name": "基础管理",
"pId": "0",
"id": "1",
"children": [{
"level": 2,
"icon": "user-icon",
"name": "用户管理",
"pId": "1",
"id": "2",
"children": [{
"level": 3,
"icon": "user-add-icon",
"name": "添加用户",
"pId": "2",
"id": "4",
"children": [{
"children": [],
"level": 4,
"icon": "user-menu-add-icon",
"name": "添加用户并分配菜单",
"pId": "4",
"id": "8"
}]
}, {
"children": [],
"level": 3,
"icon": "user-edit-icon",
"name": "编辑用户",
"pId": "2",
"id": "5"
}]
}, {
"level": 2,
"icon": "menu-icon",
"name": "菜单管理",
"pId": "1",
"id": "3",
"children": [{
"children": [{
"children": [],
"level": 4,
"icon": "user-menu-add-icon",
"name": "添加用户并分配菜单",
"pId": "4",
"id": "8"
}],
"level": 3,
"icon": "user-add-icon",
"name": "添加用户",
"pId": "2",
"id": "4"
}, {
"children": [],
"level": 3,
"icon": "user-edit-icon",
"name": "编辑用户",
"pId": "2",
"id": "5"
}]
}]
}]