类似于地区树形结构的构造

在做项目中经常会用到地区的树形结构,而在数据库中我们一般存储的是一个地区ID,该地区对应的父节点ID,地区名称。下面仅以安徽省为例展示地区表结构:省 - 市 - 县

areaId  parentId  areaName

136 13 淮南市
135 13 蚌埠市
143 13 阜阳市
139 13 铜陵市
149 13 宣城市
133 13 合肥市
147 13 亳州市
138 13 淮北市
142 13 滁州市

 

。。。。。。

 

856 135 怀远县

857 135 五河县

858 135 固镇县

 

。。。。。。

 

 

需要列出中国每个省下面的市和县。

一种方法是通过表的自连接查询实现,这里不再描述。

第二种方法通过一次sql查询出所有的数据,接着通过递归技术每个省-市,每个省-(市、县)或只有县。

 

    // typeMap 生成t_area表中父节点的所有子孙节点
    Map<Integer, Set<Integer>> typeMap = new HashMap<Integer, Set<Integer>>(); 
    //  typeDirectMap 生成t_area表中父节点的所有直接子节点
    Map<Integer, Set<Integer>> typeDirectMap = new HashMap<Integer, Set<Integer>>(); // parentKey-typeKey
    
       
        List<TArea> areaList = areaService.getArea();
        for (TArea area : areaList) {
            Integer typeKey = area.getTypeKey();
            Integer parentKey = area.getParentKey();
            Set<Integer> set = typeMap.get(parentKey);
            if (null != set) {
                set.add(typeKey);
            } else {
                Set<Integer> newSet = new CopyOnWriteArraySet<Integer>();
                newSet.add(typeKey);
                typeMap.put(parentKey, newSet);
            }
        }
        
        typeDirectMap.putAll(typeMap);
        
        traverseTypeMap(typeMap);
        

 

 

/**
     * 遍历typeMap中所有parent下面的直接child.
     * 
     * @param typeMap
     */
    private static void traverseTypeMap(Map<Integer, Set<Integer>> typeMap) {
        Set<Entry<Integer, Set<Integer>>> set = typeMap.entrySet();
        for (Entry<Integer, Set<Integer>> entry : set) {
            Integer parentKey = entry.getKey();
            Set<Integer> childSet = entry.getValue();
            traverseChild(childSet, parentKey, typeMap);
        }
    }

 

 

/**
     * 遍历childSet
     * 
     * @param childSet
     * @param pk
     * @param typeMap
     */
    private static void traverseChild(Set<Integer> childSet, Integer pk,
            Map<Integer, Set<Integer>> typeMap) {
        for (Integer child : childSet) {
            addAllChildToParent(pk, typeMap, child);
        }
    }

 

 

/**
     * 
     * @param pk 父节点
     * @param typeMap
     * @param ch  子节点
     */
    private static void addAllChildToParent(Integer pk, Map<Integer, Set<Integer>> typeMap, Integer ch) {
        Set<Integer> set = typeMap.get(pk);
        Set<Integer> chSet = typeMap.get(ch);

        if (null != chSet) {
            Set<Integer> parentSet = new HashSet<Integer>();
            addParent(typeMap, pk, parentSet);
            for (Integer p : parentSet) {
                typeMap.get(p).addAll(chSet); // 把当前子节点的集合加入到父节点的所有祖先集合中
            }
            set.addAll(chSet); // 把当前子节点的集合加入到父节点集合中
            traverseChild(chSet, ch, typeMap);
        } else { // 当前子节点集合为空 返回
            return;
        }
    }

 

 

/**
     * 把当前节点pk的所有祖先节点加入到parentSet中.
     * 
     * @param typeMap
     * @param pk
     * @param parentSet
     */
    private static void addParent(Map<Integer, Set<Integer>> typeMap, Integer pk, Set<Integer> parentSet) {
        Set<Entry<Integer, Set<Integer>>> set = typeMap.entrySet();
        for (Entry<Integer, Set<Integer>> entry : set) {
            Integer key = entry.getKey();
            Set<Integer> value = entry.getValue();
            if (value.contains(pk)) {
                parentSet.add(key);
                addParent(typeMap, key, parentSet);
            } else {
                return; // 是顶级父节点
            }
        }
    }

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值