在項目中總是有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 ;
}