java遞歸和反向遞歸


1. 遞歸查詢樹tree結構有兩種做法

第一種,遞歸查詢數據庫結構,

第二種,一次性將數據庫表中的所有數據查出來,然后再遞歸查出來的list集合,

第一種做法適合數據量較少的tree結構,因為要一直查詢數據庫數據量大時速度回相對較慢,所以數據量大時建議使用第二種方法,如圖1所示是一個常見的樹tree結構

圖1

 

2. 反向遞歸(逆向遞歸)查詢樹tree結構根據關鍵字過濾數據

大家有么有遇到過這個問題:我想要根據關鍵字過濾查詢出相關數據和它的上級結構,得到圖1所示結果,可往往不知道怎么做,查不出上級結構總是得到圖3類似的結構,要解決這個比較常見的問題就要用到反向遞歸的算法,網上我那個網搜不到類似的解決方案,本人一時興趣來了,做了一套遞歸和反遞歸的解決方案,簡單易懂,大家可以相互交流一下

圖2

圖3

3.示例代碼

 

[java]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. /** 
  2.     * 說明方法描述:將list轉為樹tree結構 
  3.     *  
  4.     * @param allRrecords 
  5.     * @return 
  6.     * @time 2016年5月10日 下午6:00:35 
  7.     * @author yangdong 
  8.     */  
  9.    public List<Record> useListRecordToTree(List<Record> allRrecords) {  
  10.   
  11.        List<Record> listParentRecord = new ArrayList<Record>();  
  12.        List<Record> listNotParentRecord = new ArrayList<Record>();  
  13.        // 第一步:遍歷allRrecords保存所有數據的uuid用於判斷是不是根節點  
  14.        Map<String, String> mapAllUuid = new HashMap<String, String>();  
  15.        Map<String, Record> allRecordMap = new HashMap<String, Record>();  
  16.        for (Record record : allRrecords) {  
  17.            mapAllUuid.put(record.getStr("uuid"), record.getStr("uuid"));  
  18.            allRecordMap.put(record.getStr("uuid"), record);  
  19.        }  
  20.        // 第二步:遍歷allRrecords找出所有的根節點和非根節點  
  21.        if (allRrecords != null && allRrecords.size() > 0) {  
  22.            for (Record record : allRrecords) {  
  23.                if (StringUtil.isBlank(record.getStr("parent_uuid"))  
  24.                    || !mapAllUuid.containsKey(record.getStr("parent_uuid"))) {  
  25.                    listParentRecord.add(record);  
  26.                } else {  
  27.                    listNotParentRecord.add(record);  
  28.                }  
  29.            }  
  30.        }  
  31.   
  32.        // 第三步: 遞歸獲取所有子節點  
  33.        if (listParentRecord.size() > 0) {  
  34.            for (Record record : listParentRecord) {  
  35.                // 添加所有子級  
  36.                record.set("childs", this.getTreeChildRecord(listNotParentRecord, record.getStr("uuid")));  
  37.            }  
  38.        }  
  39.        return listParentRecord;  
  40.    }  
  41.   
  42.    /** 
  43.     * 說明方法描述:使list轉換為樹並根據關鍵字和節點名稱過濾 
  44.     *  
  45.     * @param allRecords 所有節點 
  46.     * @param keywords 要過濾的關鍵字 
  47.     * @param filterFields 要過濾的字段 
  48.     * @return 
  49.     * @time 2016年5月19日 下午3:27:32 
  50.     * @author yangdong 
  51.     */  
  52.    public List<Record> useListRecordToTreeByKeywords(List<Record> allRecords, String keywords, String... filterFields) {  
  53.        List<Record> listRecord = new ArrayList<Record>();  
  54.        Map<String, Record> allRecordMap = new HashMap<String, Record>();  
  55.        for (Record record : allRecords) {  
  56.            allRecordMap.put(record.getStr("uuid"), record);  
  57.        }  
  58.        // 遍歷allRrecords找出所有的nodeName和關鍵字keywords相關的數據  
  59.        if (allRecords != null && allRecords.size() > 0) {  
  60.            if (filterFields.length > 1) {  
  61.                for (Record record : allRecords) {  
  62.                    for (String field : filterFields) {  
  63.                        // 比較  
  64.                        if (record.getStr(field).toLowerCase().indexOf(keywords.toLowerCase()) != -1) {  
  65.                            listRecord.add(record);  
  66.                        }  
  67.                    }  
  68.                }  
  69.            } else {  
  70.                for (Record record : allRecords) {  
  71.                    // 比較  
  72.                    if (record.getStr(filterFields[0]).toLowerCase().indexOf(keywords.toLowerCase()) != -1) {  
  73.                        listRecord.add(record);  
  74.                    }  
  75.                }  
  76.            }  
  77.        }  
  78.        // 查找過濾出來的節點和他們的父節點  
  79.        listRecord = this.getSelfAndTheirParentRecord(listRecord, new ArrayList<Record>(),  
  80.                                                      new HashMap<String, Record>(), allRecordMap);  
  81.        // 將過濾出來的數據變成樹tree結構  
  82.        listRecord = this.useListRecordToTree(listRecord);  
  83.        return listRecord;  
  84.    }  
  85.   
  86.    /** 
  87.     * 說明方法描述:遞歸查詢子節點 
  88.     *  
  89.     * @param childList 子節點 
  90.     * @param parentUuid 父節點id 
  91.     * @return 
  92.     * @time 2016年5月10日 下午3:29:35 
  93.     * @author yangdong 
  94.     */  
  95.    private List<Record> getTreeChildRecord(List<Record> childList, String parentUuid) {  
  96.        List<Record> listParentRecord = new ArrayList<Record>();  
  97.        List<Record> listNotParentRecord = new ArrayList<Record>();  
  98.        // 遍歷tmpList,找出所有的根節點和非根節點  
  99.        if (childList != null && childList.size() > 0) {  
  100.            for (Record record : childList) {  
  101.                // 對比找出父節點  
  102.                if (StringUtil.equals(record.getStr("parent_uuid"), parentUuid)) {  
  103.                    listParentRecord.add(record);  
  104.                } else {  
  105.                    listNotParentRecord.add(record);  
  106.                }  
  107.   
  108.            }  
  109.        }  
  110.        // 查詢子節點  
  111.        if (listParentRecord.size() > 0) {  
  112.            for (Record record : listParentRecord) {  
  113.                // 遞歸查詢子節點  
  114.                record.set("childs", getTreeChildRecord(listNotParentRecord, record.getStr("uuid")));  
  115.            }  
  116.        }  
  117.        return listParentRecord;  
  118.    }  
  119.   
  120.    /** 
  121.     * 說明方法描述:遞歸找出本節點和他們的父節點 
  122.     *  
  123.     * @param parentList 根據關鍵字過濾出來的相關節點的父節點 
  124.     * @param resultList 返回的過濾出來的節點 
  125.     * @param filterRecordMap 已經過濾出來的節點 
  126.     * @param allRecordMap 所有節點 
  127.     * @return 
  128.     * @time 2016年5月19日 上午9:53:56 
  129.     * @author yangdong 
  130.     */  
  131.    private List<Record> getSelfAndTheirParentRecord(List<Record> parentList, List<Record> resultList,  
  132.                                                     Map<String, Record> filterRecordMap,  
  133.                                                     Map<String, Record> allRecordMap) {  
  134.        // 當父節點為null或者節點數量為0時返回結果,退出遞歸  
  135.        if (parentList == null || parentList.size() == 0) {  
  136.            return resultList;  
  137.        }  
  138.        // 重新創建父節點集合  
  139.        List<Record> listParentRecord = new ArrayList<Record>();  
  140.        // 遍歷已經過濾出來的節點  
  141.        for (Record record : parentList) {  
  142.   
  143.            String uuid = record.getStr("uuid");  
  144.            String parent_uuid = record.getStr("parent_uuid");  
  145.   
  146.            // 如果已經過濾出來的節點不存在則添加到list中  
  147.            if (!filterRecordMap.containsKey(uuid)) {  
  148.                listParentRecord.add(record);// 添加到父節點中  
  149.                filterRecordMap.put(uuid, record);// 添加到已過濾的map中  
  150.                allRecordMap.remove(uuid);// 移除集合中相應的元素  
  151.                resultList.add(record);// 添加到結果集中  
  152.            }  
  153.   
  154.            // 找出本節點的父節點並添加到listParentRecord父節點集合中,並移除集合中相應的元素  
  155.            if (StringUtil.isNotBlank(parent_uuid)) {  
  156.                Record parentRecord = allRecordMap.get(parent_uuid);  
  157.                if (parentRecord != null) {  
  158.                    listParentRecord.add(parentRecord);  
  159.                    allRecordMap.remove(parent_uuid);  
  160.                }  
  161.            }  
  162.   
  163.        }  
  164.        // 遞歸調用  
  165.        getSelfAndTheirParentRecord(listParentRecord, resultList, filterRecordMap, allRecordMap);  
  166.   
  167.        return resultList;  
  168.    }  
[java]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. //示例  
[java]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. /** 
  2.      * 說明方法描述:遞歸查詢所有權限 
  3.      *  
  4.      * @param keyword 
  5.      * @param is_deleted 
  6.      * @return 
  7.      * @time 2016年5月10日 下午3:47:50 
  8.      * @author yangdong 
  9.      */  
  10.     public List<Record> getRecordByKeywordRecursive(String keyword, String is_deleted) {  
  11.         // 第一步:查詢所有的數據  
  12.         StringBuffer sql = new StringBuffer(  
  13.                                             " select pa.uuid,pa.parent_uuid,pa.author_code,pa.author_name,pa.is_menu,pa.sort_number,pa.is_enable,pa.menu_icon ");  
  14.         sql.append("  from s_author pa");  
  15.         List<Object> params = new ArrayList<Object>();  
  16.         sql.append(" where  pa.is_deleted=? ");  
  17.         params.add(is_deleted);  
  18.         sql.append(" order by pa.sort_number asc ");  
  19.   
  20.   
  21.         List<Record> allRrecords = Db.use(AppConst.DB_DATASOURCE_MAIN).find(sql.toString(), ParamUtil.listToArray(params));  
[java]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1.             //第二步:將list變為樹tree結構  
  2.         if (StringUtil.isNotBlank(keyword)) {  
  3.             return super.useListRecordToTreeByKeywords(allRrecords, keyword, "author_name");  
  4.         } else {  
  5.             return super.useListRecordToTree(allRrecords);  
  6.         }  
  7.     }  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM