树型构建器-TreeBuilder

原创
2015/09/19 00:48
阅读数 185
  • Tree类,entity需要继承此类

package org.blade.personal.utils.treebuilder;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Transient;

@SuppressWarnings("hiding")
public class Tree {
	
	@Transient
	private List<Tree> children = new ArrayList<Tree>();
	
	@Transient
	private boolean removed;

	private Long parentId;
	
	private Long id;

	public List<Tree> getChildren() {
		return children;
	}

	public void setChildren(List<Tree> children) {
		this.children = children;
	}

	public boolean isRemoved() {
		return removed;
	}

	public void setRemoved(boolean removed) {
		this.removed = removed;
	}

	public Long getParentId() {
		return parentId;
	}

	public void setParentId(Long parentId) {
		this.parentId = parentId;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}
	
	public void addChild(Tree tree){
		this.children.add(tree);
	}
	
}
  • TreeBuilder类,与之前的版本相比当前可以支持实体查询反回的结果

package org.blade.personal.utils.treebuilder;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.alibaba.fastjson.JSON;

public class TreeBuilder {
	/**
	 * 算法思想是: 使用map 作id 与记录的映射, 第一步把root节点找出并标记为删除;
	 * 第二步遍历记录列表取出每个的父id,然后到映射里找到相应的记录parent,把当前记录作为parent的children;
	 * 第三步把收集器里的记录转换成list。
	 * 
	 * 注意:这里使用了Map 数据结构 与 java 的 引用特性;虽然map 与 picking 是两次遍历
	 * records,但里面相同的key的记录引用 是 指向相同的内存的。
	 **/
	public static List builder(List<Tree> records) {

		// 映射id与记录成为 {id : record}
		Map<Long, Tree> map = new HashMap<Long, Tree>();
		for (Tree su : records) {
			map.put(su.getId(), su);
		}
		// 收集
		Map<Long, Tree> picking = new HashMap<Long, Tree>();
		for (Tree su : records) {
			Long parentId = su.getParentId();
			boolean removed = su.isRemoved();
			if (0 == parentId && !removed) {// 父id为0,此时为root
				picking.put(su.getId(), su);
				su.setRemoved(true);// 标记为删除,不可真删除,否则会报currencyXXXX的异常
			}
		}
		// 构建树
		for (Tree su : records) {
			Long parentId = su.getParentId();
			boolean removed = su.isRemoved();
			if (0 != parentId && !removed) {
				Tree parent = map.get(parentId);// 取出映射中的记录
				if (parent.getChildren().size() > 0) {// 是否有子节点,有把当前记录作为子节点
					List<Tree> children =  parent.getChildren();
					children.add(su);
				} else {// 无,则添加子节点容器,再把当前记录作为子节点
					List<Tree> children = new ArrayList<Tree>();
					children.add(su);
					parent.setChildren(children);
				}
				// 标记为删除,不可真删除,否则会报currencyXXXX的异常
				su.setRemoved(true);
			}
		}
		// 转为list
		List<Tree> result = new ArrayList();
		Set<Long> keySet = picking.keySet();
		for (Long key : keySet) {
			Tree resultItem = map.get(key);
			result.add(map.get(key));
		}
		return result;
	}
	
	
	public static void main(String[] args) {
		
		Tree node1 = new Tree();
		node1.setId(1L);
		node1.setParentId(0L);
		
		Tree node2 = new Tree();
		node2.setId(2L);
		node2.setParentId(1L);
		
		Tree node3 = new Tree();
		node3.setId(3L);
		node3.setParentId(1L);
		
		Tree node4 = new Tree();
		node4.setId(4L);
		node4.setParentId(3L);
		
		Tree node5 = new Tree();
		node5.setId(5L);
		node5.setParentId(4L);
		
		List list = new ArrayList();
		list.add(node1);
		list.add(node2);
		list.add(node3);
		list.add(node4);
		list.add(node5);
		
		List treeList = TreeBuilder.builder(list);
		
		System.out.println(JSON.toJSONString(treeList));
		
	/*	[{"children":[{"children":[],"id":2,"parentId":1,"removed":true},
		{"children":[{"children":[{"children":[],"id":5,"parentId":4,"removed":true}],
			"id":4,"parentId":3,"removed":true}],"id":3,"parentId":1,"removed":true}],
			"id":1,"parentId":0,"removed":true}]*/

	}
	
}


展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部