欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實(shí)現(xiàn)樹(shù)形List與扁平List互轉(zhuǎn)的示例代碼

 更新時(shí)間:2023年05月11日 10:43:53   作者:HACKYLE  
在平時(shí)的開(kāi)發(fā)中,我們時(shí)常會(huì)遇到需要將"樹(shù)形List"與"扁平List"互轉(zhuǎn)的情況,本文為大家整理了Java實(shí)現(xiàn)樹(shù)形List與扁平List互轉(zhuǎn)的示例代碼,希望對(duì)大家有所幫助

背景:在平時(shí)的開(kāi)發(fā)中,我們時(shí)常會(huì)遇到下列場(chǎng)景

  • 公司的組織架構(gòu)的數(shù)據(jù)存儲(chǔ)與展示
  • 文件夾層級(jí)的數(shù)據(jù)存儲(chǔ)與展示
  • 評(píng)論系統(tǒng)中,父評(píng)論與諸多子評(píng)論的數(shù)據(jù)存儲(chǔ)與展示
  • ......

對(duì)于這種有層級(jí)的結(jié)構(gòu)化數(shù)據(jù),就像是一棵樹(shù)一樣。在關(guān)系型數(shù)據(jù)庫(kù)中,通常將一個(gè)個(gè)的節(jié)點(diǎn)信息存儲(chǔ)到表中,通過(guò)一個(gè)字段(例如,pid),指向其父節(jié)點(diǎn)。而在數(shù)據(jù)展示的時(shí)候,我們又希望它是呈現(xiàn)層級(jí)的,例如:

id  name        pid
1   總公司       -1
2   上海分公司    1
3   浙江分公司    1
4   閔行區(qū)分公司  2
5   嘉興分公司    3
{
    "id": 1,
    "name": "總公司",
    "pid": -1,
    "branch":
    [
        {
            "id": 2,
            "name": "上海分公司",
            "pid": 1,
            "branch":
            [
                {
                    "id": 4,
                    "name": "閔行區(qū)分公司",
                    "pid": 2,
                    "branch":
                    []
                }
            ]
        },
        {
            "id": 3,
            "name": "浙江分公司",
            "pid": 1,
            "branch":
            [
                {
                    "id": 5,
                    "name": "嘉興分公司",
                    "pid": 3,
                    "branch":
                    []
                }
            ]
        }
    ]
}

所以,本文的主要內(nèi)容就是提供幾種方案,實(shí)現(xiàn)這兩類數(shù)據(jù)的轉(zhuǎn)換方式。

存儲(chǔ)樹(shù)的表結(jié)構(gòu)

如何在一張數(shù)據(jù)庫(kù)表中表示一顆樹(shù)結(jié)構(gòu)中的所有節(jié)點(diǎn)信息,這里有一個(gè)示例:

DROP TABLE IF EXISTS zj_city;
CREATE TABLE zj_city (
    id BIGINT NOT NULL AUTO_INCREMENT,
    name VARCHAR(50) COMMENT '節(jié)點(diǎn)名稱',
    pid int NOT NULL COMMENT '父節(jié)點(diǎn)',

    create_time DATETIME DEFAULT now() COMMENT '創(chuàng)建時(shí)間: 年-月-日 時(shí):分:秒',
    update_time DATETIME DEFAULT now() ON UPDATE now() COMMENT '更新時(shí)間',
    is_deleted BIT DEFAULT 0 COMMENT '是否刪除:0-false-未刪除;1-true-已刪除',
    PRIMARY KEY (id)
)COMMENT '浙江城市';

INSERT INTO zj_city(name, pid) VALUES
('浙江省',0),
('金華市',1),
('嘉興市',1),
('杭州市',1),
('寧波市',1);

INSERT INTO zj_city(name, pid) VALUES
('下城區(qū)',4),
('錢塘區(qū)',4),
('西湖區(qū)',4),
('上城區(qū)',4);

INSERT INTO zj_city(name, pid) VALUES
('南湖區(qū)',3),
('秀洲區(qū)',3),
('桐鄉(xiāng)市',3),
('平湖市',3),
('海寧市',3);

INSERT INTO zj_city(name, pid) VALUES
('梧桐街道',12),
('鳳鳴街道',12),
('龍翔街道',12),
('崇福鎮(zhèn)',12),
('烏鎮(zhèn)鎮(zhèn)',12),
('高橋鎮(zhèn)',12),
('河山鎮(zhèn)',12),
('濮院鎮(zhèn)',12);

SELECT * from zj_city;

扁平List轉(zhuǎn)樹(shù)形List

應(yīng)用場(chǎng)景

  • 公司組織結(jié)構(gòu)
  • 省市級(jí)
  • 評(píng)論系統(tǒng)中,父評(píng)論與諸多子評(píng)論
  • 其他層級(jí)展示的數(shù)據(jù)

雙層for

主要思想:外層循環(huán)-找父節(jié)點(diǎn);內(nèi)層循環(huán)-找子節(jié)點(diǎn);因?yàn)槊總€(gè)元素都會(huì)找一遍,所有最終得到完整的樹(shù)

import com.alibaba.fastjson.JSON;
import com.ks.boot.entity.CityEntity;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
public class TreeListDemo {
    List<CityEntity> cityEntities;
    /**
     * id  name  pid
     * 1   浙江   0
     * 2   杭州   1
     * 3   嘉興   1
     * 4   南湖   3
     * 5   桐鄉(xiāng)   3
     * 6   余杭   2
     * 7   西湖   2
     * 8   云南   0
     * 9   昆明   8
     * 10  昭通   8
     */
    @BeforeEach
    public void init() {
        cityEntities = JSON.parseArray("[{\"id\":1,\"name\":\"浙江\",\"pid\":0},\n" +
                "{\"id\":2,\"name\":\"杭州\",\"pid\":1},\n" +
                "{\"id\":3,\"name\":\"嘉興\",\"pid\":1},\n" +
                "{\"id\":4,\"name\":\"南湖\",\"pid\":3},\n" +
                "{\"id\":5,\"name\":\"桐鄉(xiāng)\",\"pid\":3},\n" +
                "{\"id\":6,\"name\":\"余杭\",\"pid\":2},\n" +
                "{\"id\":7,\"name\":\"西湖\",\"pid\":2},\n" +
                "{\"id\":8,\"name\":\"云南\",\"pid\":0},\n" +
                "{\"id\":9,\"name\":\"昆明\",\"pid\":8},\n" +
                "{\"id\":10,\"name\":\"昭通\",\"pid\":8}]", CityEntity.class);
    }
    @Test
    public void testList2Tree() {
        List<CityEntity> resultTree = list2Tree(this.cityEntities);
        System.out.println(JSON.toJSONString(resultTree));
    }
    /**
     * 雙層for,List轉(zhuǎn)Tree
     * 主要思想:外層循環(huán)-找父節(jié)點(diǎn);內(nèi)層循環(huán)-找子節(jié)點(diǎn);因?yàn)槊總€(gè)元素都會(huì)找一遍,所有最終得到完整的樹(shù)
     * 時(shí)間復(fù)雜度:N^2;空間復(fù)雜度:N
     */
    public List<CityEntity> list2Tree(List<CityEntity> cityEntities) {
        List<CityEntity> resultCities = new ArrayList<>();
        for (CityEntity city : cityEntities) {
            if(0 == city.getPid()) { //根節(jié)點(diǎn)、頂級(jí)節(jié)點(diǎn),直接放入最終返回結(jié)果的List
                resultCities.add(city);
            }
            for (CityEntity curCity : cityEntities) { //根據(jù)當(dāng)前city找它的子節(jié)點(diǎn)
                if(city.getId().equals(curCity.getPid())) {
                    if(city.getSubCityList() == null) { //還沒(méi)有任何子節(jié)點(diǎn),new一個(gè)空的放進(jìn)去
                        city.setSubCityList(new ArrayList<>());
                    }
                    city.getSubCityList().add(curCity);
                }
            }
        }
        return resultCities;
    }
}
public class CityEntity {
    private Long id;
    private String name;
    private Long pid;
    private List<CityEntity> subCityList;
    getter/setter
}

遞歸

主要思想:獲取所有根節(jié)點(diǎn)、頂級(jí)節(jié)點(diǎn),再?gòu)腖ist中查找根節(jié)點(diǎn)的子節(jié)點(diǎn);

import com.alibaba.fastjson.JSON;
import com.ks.boot.entity.CityEntity;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
public class TreeListDemo {
    List<CityEntity> cityEntities;
    /**
     * id  name  pid
     * 1   浙江   0
     * 2   杭州   1
     * 3   嘉興   1
     * 4   南湖   3
     * 5   桐鄉(xiāng)   3
     * 6   余杭   2
     * 7   西湖   2
     * 8   云南   0
     * 9   昆明   8
     * 10  昭通   8
     */
    @BeforeEach
    public void init() {
        cityEntities = JSON.parseArray("[{\"id\":1,\"name\":\"浙江\",\"pid\":0},\n" +
                "{\"id\":2,\"name\":\"杭州\",\"pid\":1},\n" +
                "{\"id\":3,\"name\":\"嘉興\",\"pid\":1},\n" +
                "{\"id\":4,\"name\":\"南湖\",\"pid\":3},\n" +
                "{\"id\":5,\"name\":\"桐鄉(xiāng)\",\"pid\":3},\n" +
                "{\"id\":6,\"name\":\"余杭\",\"pid\":2},\n" +
                "{\"id\":7,\"name\":\"西湖\",\"pid\":2},\n" +
                "{\"id\":8,\"name\":\"云南\",\"pid\":0},\n" +
                "{\"id\":9,\"name\":\"昆明\",\"pid\":8},\n" +
                "{\"id\":10,\"name\":\"昭通\",\"pid\":8}]", CityEntity.class);
    }
    /**
     * 遞歸,List轉(zhuǎn)Tree
     * 主要思想:獲取所有根節(jié)點(diǎn)、頂級(jí)節(jié)點(diǎn),再?gòu)腖ist中查找根節(jié)點(diǎn)的子節(jié)點(diǎn);
     * 時(shí)間復(fù)雜度:N*(1+N)/2,O(N^2),因?yàn)檫f歸方法中,最好是List的第一元素就是要找的子節(jié)點(diǎn),最壞是
     * List的最后一個(gè)元素是子節(jié)點(diǎn)
     */
    @Test
    public void testList2Tree() {
        List<CityEntity> resultCities = new ArrayList<>();
        for (CityEntity city : cityEntities) {
            if(0 == city.getPid()) { //獲取所有根節(jié)點(diǎn)、頂級(jí)節(jié)點(diǎn),再根據(jù)根節(jié)點(diǎn)進(jìn)行遞歸
                CityEntity topCity = findChild(cityEntities, city); //此時(shí)的topCity已經(jīng)包含它的所有子節(jié)點(diǎn)
                resultCities.add(topCity);
            }
        }
        System.out.println(JSON.toJSONString(resultCities));
    }
    /**
     *
     * @param cityEntities 在那個(gè)里面找
     * @param curCity 找誰(shuí)的子節(jié)點(diǎn)
     * @return curCity的子節(jié)點(diǎn)
     */
    public CityEntity findChild(List<CityEntity> cityEntities, CityEntity curCity) {
        for (CityEntity city : cityEntities) {
            if(curCity.getId().equals(city.getPid())) {
                if(null == curCity.getSubCityList()) {
                    curCity.setSubCityList(new ArrayList<>());
                }
                CityEntity subChild = findChild(cityEntities, city); //每次遞歸,都從頭開(kāi)始查找有沒(méi)有city的子節(jié)點(diǎn)
                curCity.getSubCityList().add(subChild);
            }
        }
        return curCity;
    }
}
public class CityEntity {
    private Long id;
    private String name;
    private Long pid;
    private List<CityEntity> subCityList;
    getter/setter
}

轉(zhuǎn)換為Map

主要思想

  • 在雙層for的解法中,由于內(nèi)層for也需要遍歷以便List,造成時(shí)間復(fù)雜度上身為平方級(jí)
  • 如果內(nèi)層for不需要遍歷完整的List,而是事先預(yù)處理到Map中,尋找時(shí)直接從Map中獲取,則時(shí)間復(fù)雜度降為L(zhǎng)ogN
import com.alibaba.fastjson2.JSON;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class TreeListDemo {
    List<CityEntity> cityEntities;
    /**
     * id  name  pid
     * 1   浙江   0
     * 2   杭州   1
     * 3   嘉興   1
     * 4   南湖   3
     * 5   桐鄉(xiāng)   3
     * 6   余杭   2
     * 7   西湖   2
     * 8   云南   0
     * 9   昆明   8
     * 10  昭通   8
     */
    @BeforeEach
    public void init() {
        cityEntities = JSON.parseArray("[{\"id\":1,\"name\":\"浙江\",\"pid\":0},\n" +
                "{\"id\":2,\"name\":\"杭州\",\"pid\":1},\n" +
                "{\"id\":3,\"name\":\"嘉興\",\"pid\":1},\n" +
                "{\"id\":4,\"name\":\"南湖\",\"pid\":3},\n" +
                "{\"id\":5,\"name\":\"桐鄉(xiāng)\",\"pid\":3},\n" +
                "{\"id\":6,\"name\":\"余杭\",\"pid\":2},\n" +
                "{\"id\":7,\"name\":\"西湖\",\"pid\":2},\n" +
                "{\"id\":8,\"name\":\"云南\",\"pid\":0},\n" +
                "{\"id\":9,\"name\":\"昆明\",\"pid\":8},\n" +
                "{\"id\":10,\"name\":\"昭通\",\"pid\":8}]", CityEntity.class);
    }
    /**
     * 在雙層for的解法中,由于內(nèi)層for也需要遍歷以便List,造成時(shí)間復(fù)雜度上身為平方級(jí)
     * 如果內(nèi)層for不需要遍歷完整的List,而是事先預(yù)處理到Map中,尋找時(shí)直接從Map中獲取,則時(shí)間復(fù)雜度降為L(zhǎng)ogN
     */
    @Test
    public void list2tree() {
        //收集每個(gè)PID下的節(jié)點(diǎn)為Map
        Map<Long, List<CityEntity>> cityMapByPid = cityEntities.stream().collect(Collectors.groupingBy(CityEntity::getPid));
        List<CityEntity> resultCityList = new ArrayList<>();
        for (CityEntity city : cityEntities) {
            if(0 == city.getPid()) { //根節(jié)點(diǎn)、頂點(diǎn)
                resultCityList.add(city);
            }
            List<CityEntity> citiesByPid = cityMapByPid.get(city.getId());
            if(null != citiesByPid && citiesByPid.size() > 0) { //有子節(jié)點(diǎn)
                if(null == city.getSubCityList()) {
                    city.setSubCityList(new ArrayList<>());
                }
                city.getSubCityList().addAll(citiesByPid); //塞入
            }
        }
        System.out.println(JSON.toJSONString(resultCityList));
    }
    /**
     * 簡(jiǎn)化寫法:在收集到Map時(shí),對(duì)于沒(méi)有子節(jié)點(diǎn)的節(jié)點(diǎn),創(chuàng)建一個(gè)空的塞入到Map中
     */
    @Test
    public void list2tree4Simple() {
        List<CityEntity> resultCityList = new ArrayList<>();
        //保存每個(gè)PID下的子節(jié)點(diǎn)
        Map<Long, List<CityEntity>> cityMapByPid = new HashMap<>();
        for (CityEntity city : cityEntities) { //收集每個(gè)PID下的子節(jié)點(diǎn)
            //獲取當(dāng)前PID對(duì)應(yīng)的子節(jié)點(diǎn)List,如果沒(méi)有則創(chuàng)建一個(gè)空的List塞入
            //這個(gè)設(shè)計(jì)得很巧妙
            List<CityEntity> children = cityMapByPid.getOrDefault(city.getPid(), new ArrayList<>());
            children.add(city); //插入當(dāng)前元素
            cityMapByPid.put(city.getPid(), children);
        }
        for (CityEntity city : cityEntities) {
            if(0 == city.getPid()) { //根節(jié)點(diǎn)、頂點(diǎn)
                resultCityList.add(city);
            }
            city.setSubCityList(cityMapByPid.get(city.getId()));
        }
        System.out.println(JSON.toJSONString(resultCityList));
    }
}

主要思想

收集根節(jié)點(diǎn)、頂級(jí)節(jié)點(diǎn),存入resultList,并且壓棧

循環(huán)出棧,棧元素Cur

  • 找Cur的所有子元素為child
  • 如果child不為空,則再壓入棧中。這一步的目的是,再一次找child的子元素
import com.alibaba.fastjson2.JSON;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.*;
import java.util.stream.Collectors;
public class TreeListDemo {
    List<CityEntity> cityEntities;
    /**
     * id  name  pid
     * 1   浙江   0
     * 2   杭州   1
     * 3   嘉興   1
     * 4   南湖   3
     * 5   桐鄉(xiāng)   3
     * 6   余杭   2
     * 7   西湖   2
     * 8   云南   0
     * 9   昆明   8
     * 10  昭通   8
     */
    @BeforeEach
    public void init() {
        cityEntities = JSON.parseArray("[{\"id\":1,\"name\":\"浙江\",\"pid\":0},\n" +
                "{\"id\":2,\"name\":\"杭州\",\"pid\":1},\n" +
                "{\"id\":3,\"name\":\"嘉興\",\"pid\":1},\n" +
                "{\"id\":4,\"name\":\"南湖\",\"pid\":3},\n" +
                "{\"id\":5,\"name\":\"桐鄉(xiāng)\",\"pid\":3},\n" +
                "{\"id\":6,\"name\":\"余杭\",\"pid\":2},\n" +
                "{\"id\":7,\"name\":\"西湖\",\"pid\":2},\n" +
                "{\"id\":8,\"name\":\"云南\",\"pid\":0},\n" +
                "{\"id\":9,\"name\":\"昆明\",\"pid\":8},\n" +
                "{\"id\":10,\"name\":\"昭通\",\"pid\":8}]", CityEntity.class);
    }
    /**
     * 主要思想:
     *  收集根節(jié)點(diǎn)、頂級(jí)節(jié)點(diǎn),存入resultList,并且壓棧
     *  循環(huán)出棧,棧元素Cur
     *      找Cur的所有子元素為child
     *      如果child不為空,則再壓入棧中。這一步的目的是,再一次找child的子元素
     * 時(shí)間復(fù)雜度:N(過(guò)濾出所有跟節(jié)點(diǎn)) + 常數(shù)(出棧) * N(遍歷List找當(dāng)前節(jié)點(diǎn)的子元素)
     */
    @Test
    public void list2tree() {
        List<CityEntity> resultCityList = new ArrayList<>();
        Stack<CityEntity> stack = new Stack<>();
        resultCityList = cityEntities.stream().filter(ele -> 0 == ele.getPid()).collect(Collectors.toList());
        stack.addAll(resultCityList); //根節(jié)點(diǎn)、頂點(diǎn)入棧
        while(!stack.isEmpty()) {
            CityEntity curCity = stack.pop();
            List<CityEntity> child = cityEntities.stream().filter(ele -> curCity.getId().equals(ele.getPid())).collect(Collectors.toList());
            if(!child.isEmpty()) { //這一步處理的原因是:當(dāng)沒(méi)有子元素,不顯示該個(gè)字段。流處理后沒(méi)有元素只會(huì)返回空List,不會(huì)返回null
                curCity.setSubCityList(child);
            }
            if(!child.isEmpty()) {
                stack.addAll(child);
            }
        }
        System.out.println(JSON.toJSONString(resultCityList));
    }
}

樹(shù)形List轉(zhuǎn)扁平List

遞歸

主要思想:遍歷樹(shù)節(jié)點(diǎn),一個(gè)樹(shù)節(jié)點(diǎn)如果有子樹(shù),則再次遞歸此子樹(shù),直到?jīng)]有子樹(shù)為止

import com.alibaba.fastjson2.JSON;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
/**
 * id  name  pid
 * 1   浙江   0
 * 2   杭州   1
 * 3   嘉興   1
 * 4   南湖   3
 * 5   桐鄉(xiāng)   3
 * 6   余杭   2
 * 7   西湖   2
 * 8   云南   0
 * 9   昆明   8
 * 10  昭通   8
 */
public class ListTreeDemo {
    List<CityEntity> treeList;
    @BeforeEach
    public void init() {
        treeList = JSON.parseArray("[{\"id\":1,\"name\":\"浙江\",\"pid\":0,\"subCityList\":[" +
                "{\"id\":2,\"name\":\"杭州\",\"pid\":1,\"subCityList\":[{\"id\":6,\"name\":\"余杭\",\"pid\":2},{\"id\":7,\"name\":\"西湖\",\"pid\":2}]}," +
                "{\"id\":3,\"name\":\"嘉興\",\"pid\":1,\"subCityList\":[{\"id\":4,\"name\":\"南湖\",\"pid\":3},{\"id\":5,\"name\":\"桐鄉(xiāng)\",\"pid\":3}]}]}," +
                "{\"id\":8,\"name\":\"云南\",\"pid\":0,\"subCityList\":[{\"id\":9,\"name\":\"昆明\",\"pid\":8},{\"id\":10,\"name\":\"昭通\",\"pid\":8}]}]", CityEntity.class);
    }
    @Test
    public void tree2list() {
        List<CityEntity> resList = new ArrayList<>();
        //這一層for的目的是:遍歷根節(jié)點(diǎn)
        for (CityEntity city : treeList) {
            reversion(city,resList);
        }
        System.out.println(JSON.toJSONString(resList));
    }
    public void reversion(CityEntity curNode, List<CityEntity> resList) {
        resList.add(beanCopy(curNode));
        List<CityEntity> subCityList = curNode.getSubCityList();
        if(subCityList != null && !subCityList.isEmpty()) {
            for (CityEntity city : subCityList) { //遞歸尋找子節(jié)點(diǎn)的子節(jié)點(diǎn)們
                reversion(city, resList);
            }
        }
        //遞歸的出口就是subCityList為null或者empty
    }
    private CityEntity beanCopy(CityEntity source) {
        CityEntity res = new CityEntity();
        res.setId(source.getId());
        res.setName(source.getName());
        res.setPid(source.getPid());
        return res;
    }
}

主要思想

依次遍歷樹(shù)形List,當(dāng)前節(jié)點(diǎn)為Cur

  • 將Cur收集到某個(gè)存儲(chǔ)結(jié)果的List
  • 如果Cur有子樹(shù),壓入某個(gè)棧中

依次彈出棧元素,當(dāng)前彈出的元素為StackSubTree

  • 如果StackSubTree還有子樹(shù),繼續(xù)壓棧
  • 如果StackSubTree沒(méi)有子樹(shù),則放入結(jié)果List
import com.alibaba.fastjson2.JSON;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * id  name  pid
 * 1   浙江   0
 * 2   杭州   1
 * 3   嘉興   1
 * 4   南湖   3
 * 5   桐鄉(xiāng)   3
 * 6   余杭   2
 * 7   西湖   2
 * 8   云南   0
 * 9   昆明   8
 * 10  昭通   8
 */
public class ListTreeDemo {
    List<CityEntity> treeList;

    @BeforeEach
    public void init() {
        treeList = JSON.parseArray("[{\"id\":1,\"name\":\"浙江\",\"pid\":0,\"subCityList\":[" +
                "{\"id\":2,\"name\":\"杭州\",\"pid\":1,\"subCityList\":[{\"id\":6,\"name\":\"余杭\",\"pid\":2},{\"id\":7,\"name\":\"西湖\",\"pid\":2}]}," +
                "{\"id\":3,\"name\":\"嘉興\",\"pid\":1,\"subCityList\":[{\"id\":4,\"name\":\"南湖\",\"pid\":3},{\"id\":5,\"name\":\"桐鄉(xiāng)\",\"pid\":3}]}]}," +
                "{\"id\":8,\"name\":\"云南\",\"pid\":0,\"subCityList\":[{\"id\":9,\"name\":\"昆明\",\"pid\":8},{\"id\":10,\"name\":\"昭通\",\"pid\":8}]}]", CityEntity.class);
    }

    /**
     * 1. 依次遍歷樹(shù)形List,當(dāng)前節(jié)點(diǎn)為Cur
     *   a) 將Cur收集到某個(gè)存儲(chǔ)結(jié)果的List
     *   b) 如果Cur有子樹(shù),壓入某個(gè)棧中
     * 2. 依次彈出棧元素,當(dāng)前彈出的元素為StackSubTree
     *   a) 如果StackSubTree還有子樹(shù),繼續(xù)壓棧
     *   b) 如果StackSubTree沒(méi)有子樹(shù),則放入結(jié)果List
     */
    @Test
    public void tree2list() {
        List<CityEntity> resList = new ArrayList<>();

        Stack<List<CityEntity>> stack = new Stack<>();

        for (CityEntity curCity : treeList) {
            resList.add(beanCopy(curCity));
            if (curCity.getSubCityList() != null && !curCity.getSubCityList().isEmpty()) {
                stack.push(curCity.getSubCityList());
            }
        }

        while (!stack.isEmpty()) {
            List<CityEntity> subTree = stack.pop();
            for (CityEntity city : subTree) {
                if (city.getSubCityList() != null && !city.getSubCityList().isEmpty()) {
                    stack.push(city.getSubCityList());
                } else {
                    resList.add(beanCopy(city));
                }
            }
        }

        System.out.println(JSON.toJSONString(resList));
    }

    private CityEntity beanCopy(CityEntity source) {
        CityEntity res = new CityEntity();
        res.setId(source.getId());
        res.setName(source.getName());
        res.setPid(source.getPid());
        return res;
    }
}

到此這篇關(guān)于Java實(shí)現(xiàn)樹(shù)形List與扁平List互轉(zhuǎn)的示例代碼的文章就介紹到這了,更多相關(guān)Java樹(shù)形List與扁平List互轉(zhuǎn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java字符串替換函數(shù)replace()用法解析

    Java字符串替換函數(shù)replace()用法解析

    這篇文章主要介紹了Java字符串替換函數(shù)replace()用法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • Spring中的聲明式事務(wù)控制詳解

    Spring中的聲明式事務(wù)控制詳解

    這篇文章主要介紹了Spring中的聲明式事務(wù)控制詳解,Spring的聲明式事務(wù)顧名思義就是采用聲明的方式來(lái)處理事務(wù),這里所說(shuō)的聲明,就是指在配置文件中聲明,用在Spring配置文件中聲明式的事務(wù)處理來(lái)代替代碼是的處理事務(wù),需要的朋友可以參考下
    2024-01-01
  • 詳解JAVA類加載機(jī)制

    詳解JAVA類加載機(jī)制

    這篇文章主要介紹了JAVA類加載機(jī)制的相關(guān)知識(shí),文中代碼非常詳細(xì),供大家參考和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • JAVA獲取rabbitmq消息總數(shù)過(guò)程詳解

    JAVA獲取rabbitmq消息總數(shù)過(guò)程詳解

    這篇文章主要介紹了JAVA獲取rabbitmq消息總數(shù)過(guò)程詳解,公司使用的是rabbitMQ,需要做監(jiān)控預(yù)警的job去監(jiān)控rabbitMQ里面的堆積消息個(gè)數(shù),如何使用rabbitMQ獲取監(jiān)控的隊(duì)列里面的隊(duì)列消息個(gè)數(shù)呢,需要的朋友可以參考下
    2019-07-07
  • 如何用Dos命令運(yùn)行Java版HelloWorld你知道嗎

    如何用Dos命令運(yùn)行Java版HelloWorld你知道嗎

    這篇文章主要介紹了在dos窗口中編譯和運(yùn)行java文件的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • IDEA高效使用設(shè)置指南

    IDEA高效使用設(shè)置指南

    本文主要為大家介紹了關(guān)于IDEA高效的設(shè)置指南,其中包含必備的一些插件推薦以及主題優(yōu)化還有IDEA源碼的閱讀技巧,干貨滿滿,有需要的朋友可以借鑒參考下
    2022-01-01
  • Spring Boot應(yīng)用配置常用相關(guān)視圖解析器詳解

    Spring Boot應(yīng)用配置常用相關(guān)視圖解析器詳解

    這篇文章主要給大家介紹了關(guān)于Spring Boot應(yīng)用配置常用相關(guān)視圖解析器的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-12-12
  • 使用JAVA命令運(yùn)行JAR包以及日志輸出詳解

    使用JAVA命令運(yùn)行JAR包以及日志輸出詳解

    這篇文章主要給大家介紹了關(guān)于使用JAVA命令運(yùn)行JAR包以及日志輸出的相關(guān)資料,文中通過(guò)代碼示例介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用java具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-09-09
  • Quarkus中ConfigSourceInterceptor的加密配置實(shí)現(xiàn)

    Quarkus中ConfigSourceInterceptor的加密配置實(shí)現(xiàn)

    這篇文章主要為大家介紹Quarkus中ConfigSourceInterceptor加密配置的實(shí)現(xiàn)方式,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-02-02
  • 跳表的由來(lái)及Java實(shí)現(xiàn)詳解

    跳表的由來(lái)及Java實(shí)現(xiàn)詳解

    跳表(Skip List)是一種基于鏈表的數(shù)據(jù)結(jié)構(gòu),它可以支持快速的查找、插入、刪除操作,本文主要來(lái)和大家講講跳表的由來(lái)與實(shí)現(xiàn),感興趣的小伙伴可以了解一下
    2023-06-06

最新評(píng)論