最近在做小需求的时候,需要用到目录树,特地写了一个基于java的实现。
由于需求原因,目前只实现了读部分的功能--如何将平面节点build成树。动态新增,删除等功能尚未实现。
目录结构概念:
Node:目录节点,具备节点属性信息
NodeSTore:平面目录节点持久化接口,提供方法如下:
public List findByType(String type); -- 根据目录类型,获取该类型下所有的节点(平面节点)
public void add(T node);--将增加节点持久化
public void update(T node);--将修改节点持久化
public void delete(T node);--删除节点
public void move(T src, T target); --将移动节点持久化
NodeSTore是一个接口,可以基于DB实现,也可以基于XML实现,或则其他你需要的方式。
Tree:目录树,主要职责:
通过NodeSTore load某一类型目录的所有平面节点,build成树;
根据节点id号,查找相应的节点信息
动态新增,修改,删除,移动节点,通过NodeSTore将变化持久化;
目录结构实现类图:(目前只实现了读方法)
附上Node,Tree类的核心代码
Node.java
1 public class Node implements Serializable, Comparable {23 private static final long serialVersionUID = 8085266615416399579L;45 private Integer id; // id号6 private Integer parentId;// 父亲id号7 private String name;// 目录名8 private String description;// 目录描述9 private String type;// 目录类型1011 private Node parent;// 父亲12 private List children;// 儿子1314 /**15 * 添加子节点,并且建立与当前节点的父子关系16 *17 * @param child 儿子节点18 */19 public void addChild(Node child) {20 if (child == null) {21 return;22 }23 // 设置当前节点为child的父节点24 child.setParent(this);25 // 当前节点增加child为儿子节点26 if (getChildren() == null) {27 setChildren(new ArrayList());28 }29 getChildren().add(child);30 }3132 /**33 * 删除子节点,并且建立与当前节点的父子关系34 *35 * @param child 儿子节点36 */37 public void removeChild(Node child) {38 if (child == null) {39 return;40 }41 // 将child节点的父节点清空42 child.setParent(null);43 if (getChildren() == null) {44 return;45 }46 // 当前节点删除child这个儿子节点47 getChildren().remove(child);48 }4950 /**51 * 得到全路径52 *53 * @param sep 分隔符号54 * @return55 */56 public String getPathName(String sep) {57 String pathName = getName();58 if (getParent() != null) {59 pathName = getParent().getPathName(sep) + sep + pathName;60 }61 return pathName;62 }6364 /**65 * 判断是否root节点66 *67 * @return68 */69 public boolean isRootNode() {70 return getParentId() == -1;71 }7273 /**74 * 判断是否是叶子节点75 *76 * @return77 */78 public boolean isEndNode() {79 return getChildren() == null || getChildren().isEmpty();80 }8182 /**83 * 对当前节点的儿子节点进行排序84 */85 public void sortChildren() {86 if (isEndNode()) {87 return;88 }89 Collections.sort(getChildren());90 }9192 /**93 * 对当前节点的所有儿子节点进行排序94 */95 public void sortAllChidren() {96 if (isEndNode()) {97 return;98 }99 List children = getChildren();100 Collections.sort(children);101 for (Node child : children) {102 child.sortAllChidren();103 }104 }105106 /**107 * 将虚拟目录转换成JSONObject对象108 *
109 * 本身转换包含id、name两个属性,子节点转换为children属性的数组110 *
111 *112 * @return113 */114 public JSONObject toJson() {115 JSONObject jsonObject = new JSONObject();116 try {117 jsonObject.put("id", id);118 jsonObject.put("name", name);119 if (!isEndNode()) {120 JSONArray jsonArray = new JSONArray();121 for (Node child : getChildren()) {122 jsonArray.put(child.toJson());123 }124 jsonObject.put("children", jsonArray);125 }126 } catch (JSONException e) {127 // ignore128 }129 return jsonObject;130 }131132 @Override133 public int compareTo(Node o) {134 return this.getId().compareTo(o.getId());135 }136137 }
Tree.java:
1 public class Tree {23 private String type;4 private Node root; // root节点5 private Map nodeHolder = new HashMap();// 节点持有器67 private NodeSTore nodeSTore;89 /**10 * 将平面的node list构建成树11 *12 * @throws TreeException13 */14 public void build() throws TreeException {15 List nodes = nodeSTore.findByType(type);16 // 如果nodes为空,则不做任何处理17 if (nodes == null || nodes.isEmpty()) {18 return;19 }20 // 设置root和node持有器21 for (T node : nodes) {22 if (node.isRootNode()) {23 this.root = node;24 }25 nodeHolder.put(node.getId(), node);26 }2728 // 如果root为空,则build失败了29 if (root == null) {30 throw new TreeException("no root node found.");31 }3233 // 建立节点之前关系34 for (T node : nodes) {35 if (node.isRootNode()) {36 continue;37 }38 Node parent = getNodeById(node.getParentId());39 if (parent == null) {40 throw new TreeException("no parent node found.current node id is:" + node.getId());41 }42 parent.addChild(node);43 }4445 // 排序46 root.sortAllChidren();47 }4849 /**50 * 得到root节点51 *52 * @return53 */54 public Node getRoot() {55 return root;56 }5758 /**59 * 根据id得到对应节点60 *61 * @param id62 * @return63 */64 public Node getNodeById(Integer id) {65 return nodeHolder.get(id);66 }6768 public void setType(String type) {69 this.type = type;70 }7172 public void setNodeSTore(NodeSTore nodeSTore) {73 this.nodeSTore = nodeSTore;74 }7576 }
本文配套源码
旅行要学会随遇而安,淡然一点,走走停停,