整體思路是將之前的對象,用List<Map<String, Object>>的方式包起來锅移。
Map作為樹中的“節(jié)點(diǎn)”熔掺,其中有兩個(gè)key,data--數(shù)據(jù)本身非剃,children--又一個(gè)List<Map<String, Object>>存放子“節(jié)點(diǎn)”置逻。
總的來說分兩步。
第一步努潘,將所有parent值為null的節(jié)點(diǎn)先放入最后返回的結(jié)果集中诽偷。
因?yàn)檫@些值沒有父節(jié)點(diǎn),必定在樹型結(jié)果集的第一層疯坤,可以率先放入报慕。
由于是制作成工具,所以取id和parentId的操作使用了反射压怠。
DATA_FIELD其實(shí)就是字符串常量眠冈,也就是上方提到的map中的"data"字段。
map.put((String) getSelfIdMethod.invoke(node), true)這句話后面會做解釋菌瘫。
第二步蜗顽,遍歷所有列表數(shù)據(jù),并依次添加進(jìn)現(xiàn)有的樹型結(jié)果集中雨让。
同理雇盖,map.put((String)getSelfIdMethod.invoke(node), true)同理這句話后面作解釋。
在理解了這兩個(gè)核心步驟的前提下栖忠,現(xiàn)在來解釋關(guān)于上面方法中的map的問題崔挖。
上面的方法存在一個(gè)問題,就是列表結(jié)果集(list)本身數(shù)據(jù)的順序是數(shù)據(jù)庫查出來的庵寞,也就是不確定的狸相。
如果按照順序方式只遍歷一遍來放入樹型結(jié)果集(resultList)中,那么有可能出現(xiàn)這樣一種情況捐川。
如:節(jié)點(diǎn)B的父節(jié)點(diǎn)是A脓鹃,同樣A也有父節(jié)點(diǎn)(有父節(jié)點(diǎn)的意思是不保證A在第一步中會被率先放入)。
但是在list中古沥,B是在比A更靠前的位置瘸右,所以可能出現(xiàn)娇跟,企圖將B加入樹型結(jié)果集的時(shí)候,A還不存在結(jié)果集里尊浓。
這次遍歷中逞频,B便無法放入樹型結(jié)果集中,那么如果只遍歷一次栋齿,B就被遺漏了。
目前第一版解決方案就是圖中的方法襟诸,將已經(jīng)放入resultList的節(jié)點(diǎn)存入map瓦堵。
并一直循環(huán)直到確保所有l(wèi)ist數(shù)據(jù)都放入resultList才停止。
現(xiàn)在我們能確保所有結(jié)果都能放入resultList了歌亲。但是如圖菇用,我們面臨了新的問題。
數(shù)據(jù)庫的數(shù)據(jù)如果讓數(shù)據(jù)成環(huán)陷揪,比如兩列數(shù)據(jù)互為parent這種情況惋鸥。
while (map.size() < list.size())這句代碼會讓這個(gè)方法進(jìn)入死循環(huán)。
下一節(jié)我們繼續(xù)解決這個(gè)問題悍缠。