java递归与反向递归(逆向递归)查询树tree结构根据关键字过滤数据

1 篇文章 0 订阅
1 篇文章 0 订阅

          阿里云低价服务器1折特惠,优惠爽翻天,点我立即低价购买

1. 递归查询树tree结构有两种做法

第一种,递归查询数据库结构,

第二种,一次性将数据库表中的所有数据查出来,然后再递归查出来的list集合,

第一种做法适合数据量较少的tree结构,因为要一直查询数据库数据量大时速度回相对较慢,所以数据量大时建议使用第二种方法,如图1所示是一个常见的树tree结构

图1

 

2. 反向递归(逆向递归)查询树tree结构根据关键字过滤数据

大家有么有遇到过这个问题:我想要根据关键字过滤查询出相关数据和它的上级结构,得到图1所示结果,可往往不知道怎么做,查不出上级结构总是得到图3类似的结构,要解决这个比较常见的问题就要用到反向递归的算法,网上我那个网搜不到类似的解决方案,本人一时兴趣来了,做了一套递归和反递归的解决方案,简单易懂,大家可以相互交流一下

图2

图3

3.示例代码

 

 /**
     * 说明方法描述:将list转为树tree结构
     * 
     * @param allRrecords
     * @return
     * @time 2016年5月10日 下午6:00:35
     * @author yangdong
     */
    public List<Record> useListRecordToTree(List<Record> allRrecords) {

        List<Record> listParentRecord = new ArrayList<Record>();
        List<Record> listNotParentRecord = new ArrayList<Record>();
        // 第一步:遍历allRrecords保存所有数据的uuid用于判断是不是根节点
        Map<String, String> mapAllUuid = new HashMap<String, String>();
        Map<String, Record> allRecordMap = new HashMap<String, Record>();
        for (Record record : allRrecords) {
            mapAllUuid.put(record.getStr("uuid"), record.getStr("uuid"));
            allRecordMap.put(record.getStr("uuid"), record);
        }
        // 第二步:遍历allRrecords找出所有的根节点和非根节点
        if (allRrecords != null && allRrecords.size() > 0) {
            for (Record record : allRrecords) {
                if (StringUtil.isBlank(record.getStr("parent_uuid"))
                    || !mapAllUuid.containsKey(record.getStr("parent_uuid"))) {
                    listParentRecord.add(record);
                } else {
                    listNotParentRecord.add(record);
                }
            }
        }

        // 第三步: 递归获取所有子节点
        if (listParentRecord.size() > 0) {
            for (Record record : listParentRecord) {
                // 添加所有子级
                record.set("childs", this.getTreeChildRecord(listNotParentRecord, record.getStr("uuid")));
            }
        }
        return listParentRecord;
    }

    /**
     * 说明方法描述:使list转换为树并根据关键字和节点名称过滤
     * 
     * @param allRecords 所有节点
     * @param keywords 要过滤的关键字
     * @param filterFields 要过滤的字段
     * @return
     * @time 2016年5月19日 下午3:27:32
     * @author yangdong
     */
    public List<Record> useListRecordToTreeByKeywords(List<Record> allRecords, String keywords, String... filterFields) {
        List<Record> listRecord = new ArrayList<Record>();
        Map<String, Record> allRecordMap = new HashMap<String, Record>();
        for (Record record : allRecords) {
            allRecordMap.put(record.getStr("uuid"), record);
        }
        // 遍历allRrecords找出所有的nodeName和关键字keywords相关的数据
        if (allRecords != null && allRecords.size() > 0) {
            if (filterFields.length > 1) {
                for (Record record : allRecords) {
                    for (String field : filterFields) {
                        // 比较
                        if (record.getStr(field).toLowerCase().indexOf(keywords.toLowerCase()) != -1) {
                            listRecord.add(record);
                        }
                    }
                }
            } else {
                for (Record record : allRecords) {
                    // 比较
                    if (record.getStr(filterFields[0]).toLowerCase().indexOf(keywords.toLowerCase()) != -1) {
                        listRecord.add(record);
                    }
                }
            }
        }
        // 查找过滤出来的节点和他们的父节点
        listRecord = this.getSelfAndTheirParentRecord(listRecord, new ArrayList<Record>(),
                                                      new HashMap<String, Record>(), allRecordMap);
        // 将过滤出来的数据变成树tree结构
        listRecord = this.useListRecordToTree(listRecord);
        return listRecord;
    }

    /**
     * 说明方法描述:递归查询子节点
     * 
     * @param childList 子节点
     * @param parentUuid 父节点id
     * @return
     * @time 2016年5月10日 下午3:29:35
     * @author yangdong
     */
    private List<Record> getTreeChildRecord(List<Record> childList, String parentUuid) {
        List<Record> listParentRecord = new ArrayList<Record>();
        List<Record> listNotParentRecord = new ArrayList<Record>();
        // 遍历tmpList,找出所有的根节点和非根节点
        if (childList != null && childList.size() > 0) {
            for (Record record : childList) {
                // 对比找出父节点
                if (StringUtil.equals(record.getStr("parent_uuid"), parentUuid)) {
                    listParentRecord.add(record);
                } else {
                    listNotParentRecord.add(record);
                }

            }
        }
        // 查询子节点
        if (listParentRecord.size() > 0) {
            for (Record record : listParentRecord) {
                // 递归查询子节点
                record.set("childs", getTreeChildRecord(listNotParentRecord, record.getStr("uuid")));
            }
        }
        return listParentRecord;
    }

    /**
     * 说明方法描述:递归找出本节点和他们的父节点
     * 
     * @param parentList 根据关键字过滤出来的相关节点的父节点
     * @param resultList 返回的过滤出来的节点
     * @param filterRecordMap 已经过滤出来的节点
     * @param allRecordMap 所有节点
     * @return
     * @time 2016年5月19日 上午9:53:56
     * @author yangdong
     */
    private List<Record> getSelfAndTheirParentRecord(List<Record> parentList, List<Record> resultList,
                                                     Map<String, Record> filterRecordMap,
                                                     Map<String, Record> allRecordMap) {
        // 当父节点为null或者节点数量为0时返回结果,退出递归
        if (parentList == null || parentList.size() == 0) {
            return resultList;
        }
        // 重新创建父节点集合
        List<Record> listParentRecord = new ArrayList<Record>();
        // 遍历已经过滤出来的节点
        for (Record record : parentList) {

            String uuid = record.getStr("uuid");
            String parent_uuid = record.getStr("parent_uuid");

            // 如果已经过滤出来的节点不存在则添加到list中
            if (!filterRecordMap.containsKey(uuid)) {
                listParentRecord.add(record);// 添加到父节点中
                filterRecordMap.put(uuid, record);// 添加到已过滤的map中
                allRecordMap.remove(uuid);// 移除集合中相应的元素
                resultList.add(record);// 添加到结果集中
            }

            // 找出本节点的父节点并添加到listParentRecord父节点集合中,并移除集合中相应的元素
            if (StringUtil.isNotBlank(parent_uuid)) {
                Record parentRecord = allRecordMap.get(parent_uuid);
                if (parentRecord != null) {
                    listParentRecord.add(parentRecord);
                    allRecordMap.remove(parent_uuid);
                }
            }

        }
        // 递归调用
        getSelfAndTheirParentRecord(listParentRecord, resultList, filterRecordMap, allRecordMap);

        return resultList;
    }
//示例
/**
     * 说明方法描述:递归查询所有权限
     * 
     * @param keyword
     * @param is_deleted
     * @return
     * @time 2016年5月10日 下午3:47:50
     * @author yangdong
     */
    public List<Record> getRecordByKeywordRecursive(String keyword, String is_deleted) {
        // 第一步:查询所有的数据
        StringBuffer sql = new StringBuffer(
                                            " select pa.uuid,pa.parent_uuid,pa.author_code,pa.author_name,pa.is_menu,pa.sort_number,pa.is_enable,pa.menu_icon ");
        sql.append("  from s_author pa");
        List<Object> params = new ArrayList<Object>();
        sql.append(" where  pa.is_deleted=? ");
        params.add(is_deleted);
        sql.append(" order by pa.sort_number asc ");


        List<Record> allRrecords = Db.use(AppConst.DB_DATASOURCE_MAIN).find(sql.toString(), ParamUtil.listToArray(params));
            //第二步:将list变为树tree结构
        if (StringUtil.isNotBlank(keyword)) {
            return super.useListRecordToTreeByKeywords(allRrecords, keyword, "author_name");
        } else {
            return super.useListRecordToTree(allRrecords);
        }
    }

 

          阿里云低价服务器1折特惠,优惠爽翻天,点我立即低价购买

 

 

---------------------------------------------------------------------------------------------------------------------------------------- 

如果您认为本教程质量不错,读后觉得收获很大,预期工资能蹭蹭蹭的往上涨,那么不妨小额赞助我一下,让我有动力继续写出高质量的教程。 
   ----------------------------------------------------------------------------------------------------------------------------------------                                                           

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值