最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中如何將list轉(zhuǎn)為樹形結(jié)構(gòu)

 更新時(shí)間:2023年09月07日 14:37:17   作者:zlfjavahome  
這篇文章主要介紹了Java中如何將list轉(zhuǎn)為樹形結(jié)構(gòu),本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

在系統(tǒng)開發(fā)過程中,可能會(huì)碰到一些需求,需要構(gòu)建樹形結(jié)構(gòu),數(shù)據(jù)庫一般就使用父id來表示,比如構(gòu)建菜單、構(gòu)建地區(qū)級聯(lián)、構(gòu)建部門層級結(jié)構(gòu)等等。雖然可以通過數(shù)據(jù)庫SQL查詢,但我們一般都是通過SQL一次性查詢出所有數(shù)據(jù),在程序中處理成樹形結(jié)構(gòu)。本文講述如何將一個(gè)List<T> 處理成想要的樹形結(jié)構(gòu)。

1、自己測試過沒問題的:

/**
     * 對象List轉(zhuǎn)為Tree樹形結(jié)構(gòu)
     *
     * @param entityList       傳進(jìn)來的泛型List
     * @param primaryFieldName 主鍵名稱
     * @param parentFieldName  父級字段名稱
     * @return
     */
    public final List<Map<String, Object>> listToTree(List<Map<String, Object>> entityList, String primaryFieldName, String parentFieldName) {
        //返回的map Tree樹形結(jié)構(gòu)
        List<Map<String, Object>> treeMap = new ArrayList<>();
        //將傳進(jìn)的參數(shù)entityList轉(zhuǎn)為MapList
        List<Map<String, Object>> listMap = JSON.parseObject(JSON.toJSONString(entityList), List.class);
        //聲明一個(gè)map用來存listMap中的對象,key為對象id,value為對象本身
        Map<String, Map<String, Object>> entityMap = new Hashtable<>();
        //循環(huán)listMap把map對象put到entityMap中去
        listMap.forEach(map -> entityMap.put(map.get(primaryFieldName).toString(), map));
        //循環(huán)listMap進(jìn)行Tree樹形結(jié)構(gòu)組裝
        listMap.forEach(map -> {
            //獲取map的pid
            Object pid = map.get(parentFieldName);
            //判斷pid是否為空或者為0,為空說明是最頂級,直接add到返回的treeMap中去
            if (pid == null || StringUtils.equals(pid.toString(), "0")) {
                treeMap.add(map);
            } else {
                //如果pid不為空也不為0,是子集
                // 根據(jù)當(dāng)前map的pid獲取上級 parentMap
                Map<String, Object> parentMap = entityMap.get(pid.toString());
                if (parentMap == null) { //如果parentMap為空,則說明當(dāng)前map沒有父級,當(dāng)前map就是頂級
                    treeMap.add(map);
                } else {
                    //如果parentMap不為空,則當(dāng)前map為parentMap的子級
                    //取出parentMap的所有子級的List集合
                    List<Map<String, Object>> children = (List<Map<String, Object>>) parentMap.get("children");
                    if (children == null) {  //判斷子級集合是否為空,為空則新創(chuàng)建List
                        children = new ArrayList<>();
                        parentMap.put("children", children);
                    }
                    //把當(dāng)前map對象add到parentMap的子級List中去
                    children.add(map);
                    /**
                     * 因?yàn)閜arentMap是從entityMap中g(shù)et出來的,
                     * 而entityMap中的value又是來自于listMap對象,
                     * 所以parentMap和entityMap中的value的地址都是指向listMap中的對象,
                     * 所以parentMap的children和entityMap中的value的children改變時(shí),都會(huì)改變listMap中的對象,
                     * 這里涉及到了地址、指針,就不多說了。
                     */
                }
            }
        });
        return treeMap;
    }

2、for 方法轉(zhuǎn)樹形

public class TreeTest {
    public static void main(String[] args) {
        List<Tree> node = forMethod(treeList);
        System.out.println(node);
    }
?
    /**
     * 雙重for循環(huán)方法轉(zhuǎn)換成樹形結(jié)構(gòu)
     * @param treeList
     * @return
     */
    public static List<Tree> forMethod(List<Tree> treeList) {
        List<Tree> rootTree = new ArrayList<>();
        for (Tree tree : treeList) {
            // 第一步 篩選出最頂級的父節(jié)點(diǎn)
            if (0 == tree.getParentId()) {
                rootTree.add(tree);
            }
            // 第二步 篩選出該父節(jié)點(diǎn)下的所有子節(jié)點(diǎn)列表 
            for (Tree node : treeList) {
                if (node.getParentId().equals(tree.getId())) {
                    if (CollectionUtils.isEmpty(tree.getChildren())) {
                        tree.setChildren(new ArrayList<>());
                    }
                    tree.getChildren().add(node);
                }
            }
        }
        return rootTree;
    }
}

3、遞歸方法轉(zhuǎn)樹形

public class TreeTest {
    public static void main(String[] args) {
        List<Tree> node = recursionMethod(treeList);
        System.out.println(node);
    }
    /**
     * 遞歸方法轉(zhuǎn)換成樹形結(jié)構(gòu)
     * @param treeList
     * @return
     */
    public static List<Tree> recursionMethod(List<Tree> treeList) {
        List<Tree> trees = new ArrayList<>();
        for (Tree tree : treeList) {
            // 找出父節(jié)點(diǎn)
            if (0 == tree.getParentId()) {
                // 調(diào)用遞歸方法填充子節(jié)點(diǎn)列表
                trees.add(findChildren(tree, treeList));
            }
        }
        return trees;
    }
?
    /**
     * 遞歸方法
     * @param tree 父節(jié)點(diǎn)對象
     * @param treeList 所有的List
     * @return
     */
    public static Tree findChildren(Tree tree, List<Tree> treeList) {
        for (Tree node : treeList) {
            if (tree.getId().equals(node.getParentId())) {
                if (tree.getChildren() == null) {
                    tree.setChildren(new ArrayList<>());
                }
                // 遞歸 調(diào)用自身
                tree.getChildren().add(findChildren(node, treeList));
            }
        }
        return tree;
    }
}

 4、stream方法轉(zhuǎn)樹形

public class TreeTest {
    public static void main(String[] args) {
        List<Tree> node = recursionMethod(treeList);
        System.out.println(node);
    }
    /**
     * stream方法轉(zhuǎn)換成樹形結(jié)構(gòu)
     * @param treeList
     * @return
     */
    public static List<Tree> streamMethod(List<Tree> treeList) {
        List<Tree> list = treeList.stream()
                                  // 篩選出父節(jié)點(diǎn)
                                  .filter(t -> t.getParentId() == 0)
                                  // 設(shè)置父節(jié)點(diǎn)的子節(jié)點(diǎn)列表
                                  .map(item -> {item.setChildren(streamGetChildren(item, treeList)); return item;})
                                  .collect(Collectors.toList());
        return list;
    }
?
    /**
     * stream 方式遞歸查找子節(jié)點(diǎn)列表
     * @return
     */
    public static List<Tree> streamGetChildren(Tree tree, List<Tree> treeList) {
        List<Tree> list = treeList.stream()
                                  .filter(t -> t.getParentId().equals(tree.getId()))
                                  .map(item -> {item.setChildren(streamGetChildren(item, treeList)); return item;})
                                  .collect(Collectors.toList());
        return list;
    }
}

 5、stream 轉(zhuǎn)樹形優(yōu)化

// 第一種優(yōu)化,我們合并上述兩個(gè)方法的相同部分
public class TreeTest {
    public static void main(String[] args) {
        List<Tree> node = streamMethod(0, treeList);
        System.out.println(node);
    }
?
    /**
     * stream 方法轉(zhuǎn)換樹形結(jié)構(gòu)方法的優(yōu)化
     * @param parentId
     * @param treeList
     * @return
     */
    public static List<Tree> streamMethod(Integer parentId, List<Tree> treeList) {
        List<Tree> list = treeList.stream()
                // 篩選父節(jié)點(diǎn)
                .filter(t -> t.getParentId().equals(parentId))
                // 遞歸設(shè)置子節(jié)點(diǎn)
                .map(item -> {
                    item.setChildren(streamMethod(item.getId(), treeList));
                    return item;
                })
                .collect(Collectors.toList());
        return list;
    }
}
// 第二種優(yōu)化,只是寫法的不同,核心思路不變
public class TreeTest {
    public static void main(String[] args) {
        List<Tree> node = streamMethod(0, treeList);
        System.out.println(node);
    }
    /**
     * stream 方法轉(zhuǎn)換樹形結(jié)構(gòu)方法的優(yōu)化
     * @param parentId
     * @param treeList
     * @return
     */
    public static List<Tree> streamMethod(Integer parentId, List<Tree> treeList) {
        List<Tree> list = new ArrayList<>();
        Optional.ofNullable(treeList).orElse(new ArrayList<>())
                .stream()
                // 第一次篩選出主父節(jié)點(diǎn)列表進(jìn)入循環(huán),循環(huán)里面 進(jìn)入遞歸 篩選出遞歸傳遞的從父節(jié)點(diǎn)列表
                .filter(root -> root.getParentId().equals(parentId))
                // 遞歸,最末的父節(jié)點(diǎn)從整個(gè)列表篩選出它的子節(jié)點(diǎn)列表依次組裝
                .forEach(tree -> {
                    List<Tree> children = streamMethod(tree.getId(), treeList);
                    tree.setChildren(children);
                    list.add(tree);
                });
        return list;
    }
}

經(jīng)過上面的代碼,我們已經(jīng)成功的將 List<T> 轉(zhuǎn)換成了我們想要的樹形結(jié)構(gòu)了,但是此時(shí)有需求,要求我們文件夾名稱后面附帶文件夾包含的文件數(shù)量,

數(shù)據(jù)庫或者構(gòu)造的集合數(shù)據(jù)中的文件數(shù)量只統(tǒng)計(jì)了文件夾本身下面的文件數(shù)量,并沒有加上子文件夾里面的所有文件夾數(shù)量。我們需要將子文件夾的 count 屬性逐

級累加到父節(jié)點(diǎn)的 count 屬性中更新它。 

public class TreeTest {
    public static void main(String[] args) {
        // treeList 是已經(jīng)處理好的 樹形結(jié)構(gòu) 集合
        countHandler(treeList);
        System.out.println(treeList);
    }
?
    /**
     * 遞歸將子節(jié)點(diǎn)屬性值累加給父節(jié)點(diǎn)
     * @param treeList
     * @return
     */
    private int countHandler(List<Tree> treeList) {
        int count = 0;
        if(CollectionUtil.isEmpty(treeList)){
            return count;
        }
        for (Tree tree : treeList) {
            count += tree.getCount();
            if (CollectionUtil.isEmpty(tree.getChildren())) {
                continue;
            }
            count += countHandler(tree.getChildren());
            tree.setCount(count);
            if (tree.getParentId() == null || tree.getParentId() == 0) {
                count = 0;
            }
        }
        return count;
    }
}

到此這篇關(guān)于Java中將list轉(zhuǎn)為樹形結(jié)構(gòu)的文章就介紹到這了,更多相關(guān)java list轉(zhuǎn)樹形結(jié)構(gòu)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

高青县| 杨浦区| 东台市| 镇巴县| 息烽县| 抚顺县| 泾阳县| 荆门市| 杭锦后旗| 台东县| 思南县| 白河县| 焦作市| 克什克腾旗| 浦北县| 额敏县| 昌都县| 孝义市| 土默特右旗| 滦南县| 平遥县| 甘孜| 依兰县| 临洮县| 聂荣县| 左贡县| 沁阳市| 武乡县| 吉林市| 临城县| 瑞丽市| 宿州市| 隆德县| 龙岩市| 凉城县| 建始县| 禄劝| 岑溪市| 北安市| 大宁县| 绍兴县|