Java中List转List树的通用解决方法~

时间:2022-11-19 20:57:27

首先是父接口,想要用这个通用List树生成的话就必须实现这个接口

import java.util.List;

/**
* @author Mu
*
*/
public interface TreeRootAndAutoid {
/**
* 获取父节点号和自己的节点号
*/
Integer getParentid();

/**
*
* @return
*/
Integer getAutoid();
/**
* 获取孩子树
* @return
*/
List<TreeRootAndAutoid> getTreeChildren();

/**
* 设置孩子树
* @param list
*/
void setTreeChildren(List<TreeRootAndAutoid> list);
}
接下来时Model,主要实现了接口的四个方法

package com.gszh.wmcp.project.distribution.model;

import java.util.Date;
import java.util.List;

import com.gszh.wmcp.project.distribution.util.TreeRootAndAutoid;

public class DevSysMenu implements TreeRootAndAutoid{
private Integer autoid;

private Integer parentid;

private List<TreeRootAndAutoid> children;

public Integer getAutoid() {
return autoid;
}

public Integer getParentid() {
return parentid;
}

@Override
public List<TreeRootAndAutoid> getTreeChildren() {
// TODO Auto-generated method stub
return this.children;
}

@Override
public void setTreeChildren(List<TreeRootAndAutoid> list) {
this.children=list;

}




}
最后,就是通用的List生成树工具类了
/**
<span style="white-space:pre"> </span> * 对List中的元素根据父节点Id进行分类
<span style="white-space:pre"> </span> * @param u
<span style="white-space:pre"> </span> * @param rootId
<span style="white-space:pre"> </span> * @return
<span style="white-space:pre"> </span> */
<span style="white-space:pre"> </span>public static Map<Integer, List<TreeRootAndAutoid>> groupListByParentId(List<? extends TreeRootAndAutoid> u){
<span style="white-space:pre"> </span>//定义一个map集合用于分组
<span style="white-space:pre"> </span>  Map<Integer, List<TreeRootAndAutoid>> mapList = new HashMap<Integer, List<TreeRootAndAutoid>>();
<span style="white-space:pre"> </span>//主要是把父亲节点相同的每个数据进行分组。然后存放到以父亲节点为Key,List<T>为value的Map中<span style="white-space:pre"> </span>  
<span style="white-space:pre"> </span>  for (int i=0; i<u.size(); i++) 
<span style="white-space:pre"> </span>  {
<span style="white-space:pre"> </span>   //将循环读取的结果放入对象中
<span style="white-space:pre"> </span>  TreeRootAndAutoid TreeRootAndAutoid =u.get(i);
<span style="white-space:pre"> </span>  
<span style="white-space:pre"> </span>   //如果在这个map中包含有相同的键,这创建一个集合将其存起来
<span style="white-space:pre"> </span>   if (mapList.containsKey(TreeRootAndAutoid.getParentid())) 
<span style="white-space:pre"> </span>   {
<span style="white-space:pre"> </span>    List<TreeRootAndAutoid> syn = mapList.get(TreeRootAndAutoid.getParentid());
<span style="white-space:pre"> </span>    syn.add(TreeRootAndAutoid);
<span style="white-space:pre"> </span>    mapList.put(TreeRootAndAutoid.getParentid(), syn);
<span style="white-space:pre"> </span>   //如果没有包含相同的键,在创建一个集合保存数据
<span style="white-space:pre"> </span>   } else {
<span style="white-space:pre"> </span>   List<TreeRootAndAutoid> treeRootAndAutoids = new ArrayList<TreeRootAndAutoid>();
<span style="white-space:pre"> </span>   treeRootAndAutoids.add(TreeRootAndAutoid);
<span style="white-space:pre"> </span>   mapList.put(TreeRootAndAutoid.getParentid(), treeRootAndAutoids);
<span style="white-space:pre"> </span>   }
<span style="white-space:pre"> </span>   }
<span style="white-space:pre"> </span>  
<span style="white-space:pre"> </span>  return mapList;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>/**
<span style="white-space:pre"> </span> * 根据List创建List树
<span style="white-space:pre"> </span> * @param u
<span style="white-space:pre"> </span> * @param rootId
<span style="white-space:pre"> </span> * @throws ClassNotFoundException 
<span style="white-space:pre"> </span> * @throws IllegalAccessException 
<span style="white-space:pre"> </span> * @throws InstantiationException 
<span style="white-space:pre"> </span> */
<span style="white-space:pre"> </span>public static List<TreeRootAndAutoid> buildListTree(List<? extends TreeRootAndAutoid> u,Integer rootId,String className) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
<span style="white-space:pre"> </span>return buildTree(groupListByParentId(u), rootId,className);
<span style="white-space:pre"> </span>}


<span style="white-space:pre"> </span>/**
<span style="white-space:pre"> </span> * 根据已经分组好的List和rootId来创建List树
<span style="white-space:pre"> </span> * 
<span style="white-space:pre"> </span> * @param groupListByParentId
<span style="white-space:pre"> </span> * @param rootId
<span style="white-space:pre"> </span> */


<span style="white-space:pre"> </span>static boolean mark = false;


<span style="white-space:pre"> </span>private static List<TreeRootAndAutoid> buildTree(Map<Integer, List<TreeRootAndAutoid>> mapList, Integer rootId,String className) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>// 遍历map集合,取出根节点,这里的rootId,是指最顶层节点的父节点,不管最顶层的节点是一个还是多个
<span style="white-space:pre"> </span>List<TreeRootAndAutoid> rootList = new ArrayList<TreeRootAndAutoid>();
<span style="white-space:pre"> </span>for (Map.Entry<Integer, List<TreeRootAndAutoid>> TempMap : mapList.entrySet()) {
<span style="white-space:pre"> </span>rootList = TempMap.getValue();
<span style="white-space:pre"> </span>if (rootList.get(0).getParentid().equals(rootId) ) {
<span style="white-space:pre"> </span>mapList.remove(rootId);
<span style="white-space:pre"> </span>break;
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>Integer initSize=mapList.size();
<span style="white-space:pre"> </span>// keyList,主要用来记录找到了父亲节点的子树父亲节点ID,然后在Map中删除这些List<T>,
<span style="white-space:pre"> </span>List<Integer> keyList = new ArrayList<Integer>();
<span style="white-space:pre"> </span>// 遍历Map,由于遍历一次不一定可以全部找到字树父亲节点,所有有了上面的While循环,和KeyList.
<span style="white-space:pre"> </span>// 每当遍历一次,KeyList就记录那些找到了父亲节点的子树List<T>
<span style="white-space:pre"> </span>// 在每次遍历完成之后,通过KeyList去删除Map中对应的value(这么做的原因是因为在Map迭代的时候不允许修改其自身)
<span style="white-space:pre"> </span>while (mapList.size() != 0) {
<span style="white-space:pre"> </span>Integer size=mapList.size();
<span style="white-space:pre"> </span>for (Map.Entry<Integer, List<TreeRootAndAutoid>> firtMap : mapList.entrySet()) {
<span style="white-space:pre"> </span>// secList,一个等待挂载到父亲节点下的子树
<span style="white-space:pre"> </span>List<TreeRootAndAutoid> secList = firtMap.getValue();
<span style="white-space:pre"> </span>// 深度优先遍历
<span style="white-space:pre"> </span>for (int i = 0; i < rootList.size(); i++) {
<span style="white-space:pre"> </span>recursiveTree(rootList, secList);
<span style="white-space:pre"> </span>if (mark == true) {
<span style="white-space:pre"> </span>mark = false;
<span style="white-space:pre"> </span>keyList.add(secList.get(0).getParentid());
<span style="white-space:pre"> </span>break;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>// 这里是删除Map中已经挂载成功的子树
<span style="white-space:pre"> </span>for (int i = 0; i < keyList.size(); i++) {
<span style="white-space:pre"> </span>mapList.remove(keyList.get(i));
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>//这个判断,主要用于判断根节点的父节点Id是否输入正确。如果不正确,在遍历一遍后,mapList的长度还是会和最初的长度一样
<span style="white-space:pre"> </span>if(initSize.equals(mapList.size())){
<span style="white-space:pre"> </span>throw new RuntimeException("根节点的父节点输入错误");
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>//讲道理,在上面这些代码执行完之后,如果mapList.size()还是和之前一样,就证明已经迭代完毕,剩下的,都是一些找不到父节点的子树
<span style="white-space:pre"> </span>if(size.equals(mapList.size())){
<span style="white-space:pre"> </span>for (Map.Entry<Integer, List<TreeRootAndAutoid>> firtMap : mapList.entrySet()) {
<span style="white-space:pre"> </span>// secList,一个等待挂载到父亲节点下的子树
<span style="white-space:pre"> </span>List<TreeRootAndAutoid> secList = firtMap.getValue();
<span style="white-space:pre"> </span>//首先,创建一个节点
<span style="white-space:pre"> </span>TreeRootAndAutoid newNode=(TreeRootAndAutoid)Class.forName(className).newInstance();
<span style="white-space:pre"> </span>//设置这个节点的名称,并把这个子树挂载到这个节点下
<span style="white-space:pre"> </span>newNode.SetNodeName("无区域-节点"+secList.get(0).getParentid());
<span style="white-space:pre"> </span>newNode.setTreeChildren(secList);
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>rootList.get(0).getTreeChildren().add(newNode);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>break;
<span style="white-space:pre"> </span>}


<span style="white-space:pre"> </span>}


<span style="white-space:pre"> </span>return rootList;


<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>/**
<span style="white-space:pre"> </span> * 传递进来一个子树,一个待挂载的子树
<span style="white-space:pre"> </span> * 递归子树,直到挂载成功,或者,递归完毕。
<span style="white-space:pre"> </span> * @param list
<span style="white-space:pre"> </span> * @param chirldrenTree
<span style="white-space:pre"> </span> * @return
<span style="white-space:pre"> </span> */
<span style="white-space:pre"> </span>public static List<TreeRootAndAutoid> recursiveTree(List<TreeRootAndAutoid> list, List<TreeRootAndAutoid> chirldrenTree) {


<span style="white-space:pre"> </span>for (int i = 0; i < list.size(); i++) {
<span style="white-space:pre"> </span>if (list.get(i).getNodeAutoid() != null) {
<span style="white-space:pre"> </span>if (list.get(i).getNodeAutoid().equals(chirldrenTree.get(0).getParentid())) {
<span style="white-space:pre"> </span>list.get(i).setTreeChildren(chirldrenTree);
<span style="white-space:pre"> </span>mark = true;
<span style="white-space:pre"> </span>return list;
<span style="white-space:pre"> </span>} else if (list.get(i).getTreeChildren() != null) {
<span style="white-space:pre"> </span>list.get(i).setTreeChildren(
<span style="white-space:pre"> </span>recursiveTree(list.get(i).getTreeChildren(),
<span style="white-space:pre"> </span>chirldrenTree));
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>return list;
<span style="white-space:pre"> </span>}