基礎(chǔ)入門:基于Java實(shí)現(xiàn)的多層目錄結(jié)構(gòu)

字號(hào):

最近在做小需求的時(shí)候,需要用到目錄樹(shù),特地寫了一個(gè)基于java的實(shí)現(xiàn)。
    由于需求原因,目前只實(shí)現(xiàn)了讀部分的功能——如何將平面節(jié)點(diǎn)build成樹(shù)。動(dòng)態(tài)新增,刪除等功能尚未實(shí)現(xiàn)。
    目錄結(jié)構(gòu)概念:
    Node:目錄節(jié)點(diǎn),具備節(jié)點(diǎn)屬性信息
    NodeStore:平面目錄節(jié)點(diǎn)持久化接口,提供方法如下:
    public List findByType(String type); -- 根據(jù)目錄類型,獲取該類型下所有的節(jié)點(diǎn)(平面節(jié)點(diǎn))
    public void add(T node);--將增加節(jié)點(diǎn)持久化
    public void update(T node);--將修改節(jié)點(diǎn)持久化
    public void delete(T node);--刪除節(jié)點(diǎn)
    public void move(T src, T target); --將移動(dòng)節(jié)點(diǎn)持久化
    NodeStore是一個(gè)接口,可以基于DB實(shí)現(xiàn),也可以基于XML實(shí)現(xiàn),或則其他你需要的方式。
    Tree:目錄樹(shù),主要職責(zé):
    通過(guò)NodeStore load某一類型目錄的所有平面節(jié)點(diǎn),build成樹(shù);
    根據(jù)節(jié)點(diǎn)id號(hào),查找相應(yīng)的節(jié)點(diǎn)信息
    動(dòng)態(tài)新增,修改,刪除,移動(dòng)節(jié)點(diǎn),通過(guò)NodeStore將變化持久化;
    目錄結(jié)構(gòu)實(shí)現(xiàn)類圖:(目前只實(shí)現(xiàn)了讀方法)
    附上Node,Tree類的核心代碼
    Node.java
    1 public class Node implements Serializable, Comparable {
    2
    3 private static final long serialVersionUID = 8085266615416399579L;
    4
    5 private Integer id; // id號(hào)
    6 private Integer parentId;// 父親id號(hào)
    7 private String name;// 目錄名
    8 private String description;// 目錄描述
    9 private String type;// 目錄類型
    10
    11 private Node parent;// 父親
    12 private List children;// 兒子
    13
    14 /**
    15 * 添加子節(jié)點(diǎn),并且建立與當(dāng)前節(jié)點(diǎn)的父子關(guān)系
    16 *
    17 * @param child 兒子節(jié)點(diǎn)
    18 */
    19 public void addChild(Node child) {
    20 if (child == null) {
    21 return;
    22 }
    23 // 設(shè)置當(dāng)前節(jié)點(diǎn)為child的父節(jié)點(diǎn)
    24 child.setParent(this);
    25 // 當(dāng)前節(jié)點(diǎn)增加child為兒子節(jié)點(diǎn)
    26 if (getChildren() == null) {
    27 setChildren(new ArrayList());
    28 }
    29 getChildren().add(child);
    30 }
    31
    32 /**
    33 * 刪除子節(jié)點(diǎn),并且建立與當(dāng)前節(jié)點(diǎn)的父子關(guān)系
    34 *
    35 * @param child 兒子節(jié)點(diǎn)
    36 */
    37 public void removeChild(Node child) {
    38 if (child == null) {
    39 return;
    40 }
    41 // 將child節(jié)點(diǎn)的父節(jié)點(diǎn)清空
    42 child.setParent(null);
    43 if (getChildren() == null) {
    44 return;
    45 }
    46 // 當(dāng)前節(jié)點(diǎn)刪除child這個(gè)兒子節(jié)點(diǎn)
    47 getChildren().remove(child);
    48 }
    49
    50 /**
    51 * 得到全路徑
    52 *
    53 * @param sep 分隔符號(hào)
    54 * @return
    55 */  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 }
    63
    64 /**
    65 * 判斷是否root節(jié)點(diǎn)
    66 *
    67 * @return
    68 */
    69 public boolean isRootNode() {
    70 return getParentId() == -1;
    71 }
    72
    73 /**
    74 * 判斷是否是葉子節(jié)點(diǎn)
    75 *
    76 * @return
    77 */
    78 public boolean isEndNode() {
    79 return getChildren() == null || getChildren().isEmpty();
    80 }
    81
    82 /**
    83 * 對(duì)當(dāng)前節(jié)點(diǎn)的兒子節(jié)點(diǎn)進(jìn)行排序
    84 */
    85 public void sortChildren() {
    86 if (isEndNode()) {
    87 return;
    88 }
    89 Collections.sort(getChildren());
    90 }
    91
    92 /**
    93 * 對(duì)當(dāng)前節(jié)點(diǎn)的所有兒子節(jié)點(diǎn)進(jìn)行排序
    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 }
    105
    106 /**
    107 * 將虛擬目錄轉(zhuǎn)換成JSONObject對(duì)象
    108 *
    109 * 本身轉(zhuǎn)換包含id、name兩個(gè)屬性,子節(jié)點(diǎn)轉(zhuǎn)換為children屬性的數(shù)組
    110 *
    111 *
    112 * @return
    113 */
    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 // ignore
    128 }
    129 return jsonObject;
    130 }  131
    132 @Override
    133 public int compareTo(Node o) {
    134 return this.getId().compareTo(o.getId());
    135 }
    136
    137 }
    Tree.java:
    1 public class Tree {
    2
    3 private String type;
    4 private Node root; // root節(jié)點(diǎn)
    5 private Map nodeHolder = new HashMap();// 節(jié)點(diǎn)持有器
    6
    7 private NodeStore nodeStore;
    8
    9 /**
    10 * 將平面的node list構(gòu)建成樹(shù)
    11 *
    12 * @throws TreeException
    13 */
    14 public void build() throws TreeException {
    15 List nodes = nodeStore.findByType(type);
    16 // 如果nodes為空,則不做任何處理
    17 if (nodes == null || nodes.isEmpty()) {
    18 return;
    19 }
    20 // 設(shè)置root和node持有器
    21 for (T node : nodes) {
    22 if (node.isRootNode()) {
    23 this.root = node;
    24 }
    25 nodeHolder.put(node.getId(), node);
    26 }
    27
    28 // 如果root為空,則build失敗了
    29 if (root == null) {
    30 throw new TreeException("no root node found.");
    31 }
    32
    33 // 建立節(jié)點(diǎn)之前關(guān)系
    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 }
    44
    45 // 排序
    46 root.sortAllChidren();
    47 }
    48
    49 /**
    50 * 得到root節(jié)點(diǎn)
    51 *
    52 * @return
    53 */
    54 public Node getRoot() {
    55 return root;
    56 }
    57
    58 /**
    59 * 根據(jù)id得到對(duì)應(yīng)節(jié)點(diǎn)
    60 *
    61 * @param id
    62 * @return
    63 */
    64 public Node getNodeById(Integer id) {
    65 return nodeHolder.get(id);
    66 }
    67
    68 public void setType(String type) {
    69 this.type = type;
    70 }
    71
    72 public void setNodeStore(NodeStore nodeStore) {
    73 this.nodeStore = nodeStore;
    74 }
    75
    76 }