通过List/Map转树结构


文章目录

  • 通过List/Map转树结构
  • 前言
  • 一、代码详情
  • 1.创建接口实现公共方法
  • 2.构建树工具类
  • 3.调用示例
  • 总结



前言

仅为了记录学习过程

一、代码详情

1.创建接口实现公共方法

代码如下:

/**
 * 接口返回指定方法
 * @param <K> 返回类型
 */
interface Node3<K,T>{
	
	/**
	 * 获取node节点的Id
	 * @return
	 */
	K getNodeId();
	
	/**
	 * 获取node节点的parentId
	 * @return
	 */
	K getNodePid();
	
	/**
	 * 向children数组中添加对象
	 * @param node
	 * @return
	 */
	
	boolean addNodeChildren(T node);
	
	/**
	 * 这个方法是用户自己判断2个对象的大小,用于排序自定义列时(不是int的列)
	 * 返回需要对比值的差值,如果为字符串则返回数字负数或者正数或者0
	 * @param o 这里是对比this和o中的值区别
	 * @param isAsc 排序方式true正序/false倒序
	 * @return
	 */
	int nodeEquels(T o,boolean isAsc);
}

2.构建树工具类

代码如下:

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * 构建树节点
 * @author Mango
 * 2023-12-14 00:45:30
 * @param <T> 需要构建树的对象
 * @param <K> 构建数ID的类型
 */
public class TreeUtils3<K,T extends Node3<K,T>> {
	
	/**
	 * 定义排序支持类型
	 */
	private String[] typeNameArr = new String[] {"int","java.lang.Integer"};
	
	/**
	 * 链式调用临时参数
	 */
	private List<T> tempList = new ArrayList<>();
	
	
	/**
	 * 链式调用排序
	 * @param columnName
	 * @param isAsc
	 * @return
	 */
	public TreeUtils3<K,T> sort(String columnName,boolean isAsc) {
		this.tempList = sort(this.tempList, columnName, isAsc);
		return this;
	}
	
	/**
	 * 链式调用构件树
	 * @return
	 */
	public TreeUtils3<K,T>  bulidTree(){
		this.tempList = bulidTree(this.tempList);
		return this;
	}
	
	/**
	 * 初始化list的值
	 * @return
	 */
	public TreeUtils3<K,T> init(List<T> t){
		this.tempList = t;
		return this;
	}
	
	/**
	 * 获取list的值
	 * @return
	 */
	public List<T> end(){
		return this.tempList;
	}
	
	
	/**
	 * 排序
	 * @param sourceLsit 需要排序的List
	 * @param columnName 排序列
	 * @param isAsc 是否正序|true正,false反
	 * @return
	 */
	private List<T> sort(List<T> sourceList,String columnName,boolean isAsc) {
		try {
			//判断sourceLsit不能为空,为空直接返回空
			if(sourceList==null || sourceList.size() == 0 || columnName==null ||columnName.equals("")) {
				return new ArrayList<>();
			}
			//取出columnName字段类型
			Class<?> classT = sourceList.get(0).getClass();//获取类属性
			Field fieldColumn = classT.getDeclaredField(columnName);//获取列信息
			fieldColumn.setAccessible(true);//设置可访问私有属性
			String typeName = fieldColumn.getType().getName();
			//判断如果
			Collections.sort(sourceList, new Comparator<T>() {
				@Override
				public int compare(T o1, T o2) {
					//判断typeName不是int/Integer属性就走自定义的排序规则
					if(Arrays.asList(typeNameArr).contains(typeName)) {
						//获取到o1和o2的column值
						try {
							if(isAsc)
								return fieldColumn.getInt(o1) - fieldColumn.getInt(o2);
							else
								return fieldColumn.getInt(o2) - fieldColumn.getInt(o1);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}else {//自己处理判断逻辑
						return o1.nodeEquels(o2,isAsc);
					}
					return 0;
				}
			});
		} catch (Exception e) {
			e.printStackTrace();
			return new ArrayList<>();
		}
		return sourceList;
	}
	
	/**
	 * 根据传入的List<T>构建树
	 * @param sourceLsit 树节点
	 * @return
	 */
	private List<T> bulidTree(List<T> sourceLsit){
		//将bulidTree转为LinkedHashMap
		LinkedHashMap<K,T> sourceLinkedMap = new LinkedHashMap<>();
		for(T node:sourceLsit) {
			sourceLinkedMap.put(node.getNodeId(),node);
		}
		return bulidTree(sourceLinkedMap);
	}
	
	/**
	 * 这里传入的参数一定为LinkedHashMap
	 * 根据传入的Map<K,T>构建树,K代表数据的ID,T代表对象
	 * @param sourceLsit 树节点
	 * @return
	 */
	private List<T> bulidTree(LinkedHashMap<K,T> sourceMap){
		//使用向上查找的方式,先找到子节点放入父节点,然后记录子节点ID迭代删除,剩下的就是一棵树
		List<K> removeList = new ArrayList<>();
		for(T t : sourceMap.values()) {
			T parentNode = sourceMap.get(t.getNodePid());
			if(parentNode!=null) {
				//将当前循环的节点丢入
				parentNode.addNodeChildren(t);
				removeList.add(t.getNodeId());
			}
		}
		//删除
		removeList.forEach(sourceMap::remove);
		return new ArrayList<>(sourceMap.values());
	}
}

3.调用示例

代码如下:

public static void main(String[] args) {
		List<Node> nodeList = new ArrayList<>();
		nodeList.add(new Node("120100","120000","天津市市辖区",0));
		nodeList.add(new Node("110102","110100","西城区",1));
		nodeList.add(new Node("110100","110000","北京市市辖区",0));
		nodeList.add(new Node("120101","120100","和平区",0));
		nodeList.add(new Node("110101","110100","东城区",0));
		nodeList.add(new Node("110107","110100","石景山区",4));
		nodeList.add(new Node("500105","500100","江北区",4));
		nodeList.add(new Node("500000","000000","重庆市",0));
		nodeList.add(new Node("510104","510100","锦江区",0));
		nodeList.add(new Node("510114","510100","新都区",7));
		nodeList.add(new Node("110105","110100","朝阳区",2));
		nodeList.add(new Node("110106","110100","丰台区",3));
		nodeList.add(new Node("130000","000000","河北省",3));
		nodeList.add(new Node("120000","000000","天津市",0));
		nodeList.add(new Node("500103","500100","渝中区",2));
		nodeList.add(new Node("500104","500100","大渡口区",3));
		nodeList.add(new Node("510000","000000","四川省",0));
		nodeList.add(new Node("510100","510000","成都市区",0));
		nodeList.add(new Node("120102","120101","河东区",1));
		nodeList.add(new Node("120117","120100","宁河区",13));
		nodeList.add(new Node("500100","500000","重庆市市辖区",0));
		nodeList.add(new Node("110000","000000","北京市",0));
		nodeList.add(new Node("500102","500100","涪陵区",1));
		nodeList.add(new Node("000000","0","中国",0));
		nodeList.add(new Node("500101","500100","万州区",0));
		
		TreeUtils3<String, Node> treeUtils3 = new TreeUtils3<String, Node>();
		System.out.println(JSON.toJSONString(treeUtils3.init(nodeList).sort("gid", false).bulidTree().end()));;
		
	}

总结

该文章仅供自己学习,如果需要bug麻烦留言下谢谢。