前言:如果字段與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"
}]
}]
}]