List To Tree 及遍歷Tree

在項目中總是有Tree型的數據。在數據庫中總是會以parentId的形式存儲。一般這樣的數據都會是不常改變的數據。所以,可以將這些數據以Tree的形式存放起來,以便查看。這樣無論前臺是怎麼的樣式變化,對於後臺而言,也不會太大的變化。在這裏主要實現的是怎樣將後臺的查詢得到的List數據轉化爲Tree形式的數據結構,以及對Tree查詢結點。
在這裏可以後期補上如何在數據庫中用sql 實現樹型數據的查詢。

查詢得到的數據結構如下所示:
[{id=1,name=河南},{id=2,name=江蘇},{id=10,name=鄭州,parentId=1},{id=20,name=江蘇1,parentId=2}]

期望得到的數據結構如下:
[{id=1,name=河南,children:[{id=10,name=鄭州,parentId=1,children=-1}]},
{id=2,name=江蘇,children:[{id=20,name=江蘇1,parentId=2,children=-1}]}]

實現思路:
採用遞歸的實現方法。根據遞歸的概念,我首先要清楚什麼時候會結束遞歸,每一次遞歸操作是什麼樣的。
條件:對集合中的每一個note.parentId == root.id 是則children.add(node)
* 查詢不到子結點時,return;
* 查詢到子結點時,則children.add(node); recursion(root,集合點);
* if(children.size()>0)
* root.put(“children”,children);
* else
* root.put(“children”,”-1”)
eg:要先找出所有的一級結點。在這裏是每一個Map值 中沒有parentId的結點。
代碼實現:

public List<Map<String,Object>> getTreeResult(T clz) throws Exception{
        //反射
        Method method = clz.getClass().getMethod("selectList",
                new Class[] {String.class,String.class});
        List<Map<String,Object>> results = 
            (List<Map<String, Object>>) method.invoke(clz, new Object[] {dataSourceKey,sql});
        //以上代碼上從數據庫中查詢List<Map<String,Object    >>的結果
        List<Map<String,Object>> roots = new ArrayList<Map<String,Object>>();
        for (Map<String, Object> result : results) {
            if(!isRoot(result)){
                result.put("children", "-1");
                roots.add(result);
            }
        }
        results.removeAll(roots);
        for(int rootNext = 0;rootNext<roots.size();rootNext++){
             Map<String,Object> root = roots.get(rootNext);
             this.recursion(root,results);
        }
        return roots;
    }

    public void recursion(Map<String,Object> root,List<Map<String,Object>> nodes){
        List<Map<String,Object>> children = new ArrayList<Map<String,Object>>();
        List<Map<String,Object>> nodesCopy = nodes;
        for(int nodeNext=0;nodeNext<nodes.size();nodeNext++){
            Map<String,Object> node = nodes.get(nodeNext);
            if(node.get("parentId").equals(root.get("id"))){
                children.add(node);
                this.recursion(node, nodesCopy);
            }
        }
        if(children.size()>0){
            root.put("children", children);
        } else {
            root.put("children", "-1");
        }
        return ;
    }

    public boolean isRoot(Map<String,Object> node){
        return node.containsKey("parentId");
    }

2、對上述Tree結構,查詢id=?的結點 -遞歸
思路:
依次對每一個兄弟結點進行遍歷。如果有children則遞歸,沒有則return; 同時判斷map.get(‘id’)是否等於id 相等 則拋出異常。即強制退出遞歸。
強制退出遞歸有兩種:
*採用全局靜態變量FLAG。
* 拋出異常。

代碼如下:

public void getNodeCursion(String id,List<Map<String,Object>> nodes) throws StopMsgException{
        for (Map<String, Object> node : nodes) {
            if(!StringUtils.equals(String.valueOf((Long)node.get("id")), id)){
                if(!node.get("children").equals("-1")){
                    List<Map<String,Object>> children = 
                        (List<Map<String, Object>>) node.get("children");
                    getNodeCursion(id,children);
                }
            } else {
                throw new StopMsgException(node);
            }
        }
        return ;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章