樹形結構資料儲存方案的選擇和java list轉tree
阿新 • • 發佈:2018-12-17
樹形結構資料儲存方案
Adjacency List:每一條記錄存parent_idPath Enumerations:每一條記錄存整個tree path經過的node列舉Nested Sets:每一條記錄存 nleft 和 nrightClosure Table:維護一個表,所有的tree path作為記錄進行儲存。
各種方法的常用操作代價見下圖
一般來說,資料量小,採用適合鄰接表儲存設計,簡單靈活,而大部分情況下都不會有太大的資料,主要用於種類樹、選單樹。鄰接表再程式中的使用:直接查詢所有,然後構建樹形結構資料。有序資料構建樹,層級之間是有序的。可通過sql查詢排序。
java list轉tree
TreeNode介面
package klg.common.tree; import java.io.Serializable; import java.util.List; /** * * @author klguang * * @param <ID> */ public interface TreeNode<ID extends Serializable> { public ID getId(); public ID getParentId(); public <T extendsTreeNode<ID>> void setChildren(List<T> children); }
TreeHelper工具類
package klg.common.tree; import java.io.Serializable; import java.util.ArrayList; import java.util.List; /** * * @author klguang * */ public class TreeHelper { /** * * @paramparentID * null 為根節點 * @param nodeList * @param sort * @return */ public static <ID extends Serializable,T extends TreeNode<ID>> List<T> buildTree(ID parentID, List<T> nodeList) { // 根節點列表 List<T> list = new ArrayList<>(); // 順序遍歷節點列表,如果之前是有序的,那麼構建樹後同層級之間有序 for (int i=0; i<nodeList.size(); i++) { T node = nodeList.get(i); //遞迴入口, String.valueOf防止null值 if (String.valueOf(node.getParentId()).equals(String.valueOf(parentID))) { // parentID作為入口 List<T> children = buildTree(node.getId(), nodeList); node.setChildren(children); list.add(node); } } return list; } }
案例easyui tree
package klg.common.tree; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import javax.persistence.Access; import javax.persistence.AccessType; import javax.persistence.Column; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.MappedSuperclass; import javax.persistence.Transient; /** * * @author klguang * */ @MappedSuperclass @Access(AccessType.FIELD) public abstract class EasyUITreeNode<ID extends Serializable> implements Serializable, TreeNode<ID> { private static final long serialVersionUID = 850845227481354764L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private ID id; @Column(name = "parent_id") private ID parentId; @Column(name = "name", nullable = false) private String name; @Column(name = "icon_cls") private String iconCls; @Column(name = "state") private String state; @Column(name = "order_num") private Integer orderNum; @SuppressWarnings("rawtypes") @Transient List children = new ArrayList<>(); /** * easyui treegrid 需求格式 * * @return */ public String getText() { return this.name; } public ID getId() { return id; } public void setId(ID id) { this.id = id; } public ID getParentId() { return parentId; } public void setParentId(ID parentId) { this.parentId = parentId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getIconCls() { return iconCls; } public void setIconCls(String iconCls) { this.iconCls = iconCls; } public String getState() { return state; } public void setState(String state) { this.state = state; } public Integer getOrderNum() { return orderNum; } public void setOrderNum(Integer orderNum) { this.orderNum = orderNum; } @SuppressWarnings("unchecked") public <T extends TreeNode<ID>> List<T> getChildren() { return children; } public<T extends TreeNode<ID>> void setChildren(List<T> children) { this.children = children; } }
使用方法
easyui tree實現類
public class Permission extends EasyUITreeNode<Long> { //fields }
構建樹
public List<Permission> findAll(){ Sort sort = new Sort(Direction.ASC,"orderNum"); List<Permission> listData=permissionService.findList(sort); return TreeHelper.<Long,Permission>buildTree(null, listData); }