树生成器

这几天在写一个外快,而写之前的TT随笔比较耗时,故先搁着。

前天写了一个树生成器,感觉还是挺不错的,相对来说还是比较灵活的,代码也比较简单。

先贴上生成器的代码:

 

package com.tt.pub.utils;

import java.util.List;
import java.util.Stack;
/**
 * Desc:树生成工具。
 * @author Small
 * @Email [email protected]
 * @since 2013-6-14
 *
 */
public class TreeGen {

	/**
	 * Desc:树生成模板。
	 * @author Small
	 * @Email [email protected]
	 * @since 2013-6-14
	 *
	 * @param <E>
	 * @param <V>
	 */
	public static interface ITreeTmp<E, V> {
	
		/**
		 * Desc:将源对象转换为目标对象(树节点)。
		 * @author Small
		 * @Email [email protected]
		 * @since 2013-6-14
		 * 
		 * @param src
		 * @return
		 */
		public V trans(E src);
		
		/**
		 * Desc:是否将当前node入栈?如果入栈,请记得为节点构造父子关系。
		 * @author Small
		 * @Email [email protected]
		 * @since 2013-6-14
		 * 
		 * @param node
		 * @param lastNode
		 * @return
		 */
		public boolean isPush(V node, V lastNode);
	}

	/**
	 * Desc:通过有一定规律的数组(请先进行排序),构建树数组。
	 * @author Small
	 * @Email [email protected]
	 * @since 2013-6-14
	 * 
	 * @param srcList
	 * @param tmp
	 * @return
	 */
	public static <E, V> List<V> gen(List<E> srcList, ITreeTmp<E, V> tmp){
		List<V> treeList = CollUtils.newArrayList();
		Stack<V> stack = CollUtils.newStack();
		for(int i = 0; i < srcList.size(); ++i){
			E src = srcList.get(i);
			V node = tmp.trans(src);
			if(stack.size() == 0){//如果栈为空,则为树根
				treeList.add(node);//添加为根节点
				stack.push(node);//当前元素进栈
				continue;
			}
			while(stack.size() > 0){//进行栈操作
				V lastNode = stack.lastElement();//取顶级元素进行比较
				if(tmp.isPush(node, lastNode)) {
					stack.push(node);//当前元素进栈
					break;
				}
				else stack.pop();//未匹配到则出栈
			}
		}
		return treeList;
	}
}

 

 

 所需要的数据格式如下:

var menuInfos = [{
	id : "menu001"
},{
	id : "menu001001"
},{
	id : "menu001002"
},{
	id : "menu001002001"
},{
	id : "menu002"
},{
	id : "menu002001"
}];

 数据按一定顺序排列,并且有一定规则。

使用的范例如下:

先创建一个模板,模板需要实现TreeGen中的ITreeTmp接口:

 调用方式:

List<Pvl> menus = pvlService.getByType(PvlConst.PVL_TYPE_MENU);
List<TreeNode4EUi> treeList = TreeGen.gen(menus, new MenuTreeTmp());

 大概的思路是运用了栈来进行操作:

    如果栈为空,那么当前元素就作为根节点;

    如果当前元素是栈最后一个节点的子节点,则创建父子关系,并将当前节点推入栈;

    如果当前元素不是是栈最后一个节点的子节点,则将元素出栈,继续循环,知道创建父子关系或者栈为空。

 

 

 

后记:

实在惭愧,没有测试完整,指测试了树列表个数为1的,后面测试的时候才发现了bug。其实只要把TreeGen的gen方法中的循环部分的代码对调下就行了~~代码如下:

	public static <E, V> List<V> gen(List<E> srcList, ITreeTmp<E, V> tmp){
		List<V> treeList = CollUtils.newArrayList();
		Stack<V> stack = CollUtils.newStack();
		for(int i = 0; i < srcList.size(); ++i){
			E src = srcList.get(i);
			V node = tmp.trans(src);
			while(stack.size() > 0){//进行栈操作
				V lastNode = stack.lastElement();//取顶级元素进行比较
				if(tmp.isPush(node, lastNode)) {
					stack.push(node);//当前元素进栈
					break;
				}
				else stack.pop();//未匹配到则出栈
			}
			if(stack.size() == 0){//如果栈为空,则为树根
				treeList.add(node);//添加为根节点
				stack.push(node);//当前元素进栈
				continue;
			}
		}
		return treeList;
	}

 

猜你喜欢

转载自536762164-qq-com.iteye.com/blog/1887552