背景:在最近開發的一個管理系統中需要從數據庫查詢數據,並把這些數據組合成菜單樹返回供前端調用!
實現源碼:
private void createMenuTree(List<MenuInfo> menuInfoList, List<String> menuCodeList) {
//獲取一級節點
List<ParamInfo> paramInfoList = null;
List<MenuInfo> menuNextLevelInfoList = null;
for (MenuInfo menuInfo : menuInfoList) {
//獲取paramInfoList數據
paramInfoList = portalMenuDao.getParamInfoList(menuInfo.getCode());
menuInfo.setParamInfoList(paramInfoList);
menuNextLevelInfoList = portalMenuDao.getNextLevelMenu(menuInfo.getSysCode(), menuInfo.getCode(), menuCodeList);
if (menuNextLevelInfoList.size() > 0) {
sortMenuByOrderNum(menuNextLevelInfoList);
menuInfo.setMenuList(menuNextLevelInfoList);
//遞歸調用獲取其他子節點
createMenuTree(menuNextLevelInfoList, menuCodeList);
}
}
}
問題分析:爲啥此種方式會導致加載菜單樹慢?
因爲我們使用的是遞歸算法,遞歸算法的本質是方法自己調用自己,也就是方法無限次的進行入棧操作,棧是一種FILO的數據結構,待數據運算結束以後該方法還要經過無數次的出棧以結束此方法,當我們傳入的menuInfoList很大同時menuNextLevelInfoList也很大時那麼就會出現上述問題,就好比你打開了一個APP的一個頁面,頁面上有很多的按鈕,每個按鈕點進去又有很多的頁面,如此反覆幾次,你最後要退出APP就得一個一個頁面的關閉最終才能退出此APP(假設沒有Home鍵啦!)
關於遞歸算法詳解請移步:https://blog.csdn.net/u013185349/article/details/82744323 https://blog.csdn.net/w36680130/article/details/81535128
如何優化呢?
我們可以用二叉樹的算法來代替遞歸算法,這樣方法運行結束以後只要進行一次彈棧操作就可結束該方法。
代碼如下:
//使用二叉樹算法生成樹
private void createMneuTree(List<MenuInfo> menuInfoList, List<String> menuCodeList){
/*下一層的所有子結點*/
List<MenuInfo> menuNextLevelInfoList=null;
/*所有根節點*/
List<MenuInfo> currentRootNodeList =menuInfoList;
/*用於記錄每次循環的臨時變量*/
List<MenuInfo> tempList = null;
while (true){
menuNextLevelInfoList.clear();
for (MenuInfo m : currentRootNodeList) {
tempList = portalMenuDao.getNextLevelMenu(currentRootNodeList.getSysCode(), currentRootNodeList.getCode(), menuCodeList);
m.setMenuList(tempList);
menuNextLevelInfoList.addAll(tempList);
}
if (menuNextLevelInfoList.size()>0){
currentRootNodeList=menuNextLevelInfoList;
}else {
return;
}
}
}
問題解決!