Java用递归之外的办法组装树形结构

1.Java代码:
package com.hello.test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class ArrToTree {
	public static void main(String[] args){
	    //设置初始数据(对顺序没有要求)
		List<Node> list = new ArrayList<Node>();
		list.add(new Node(1L, null));//pid可以是null也可以是-1等不存在的id
		list.add(new Node(2L, 1L));
		list.add(new Node(3L, 1L));
		list.add(new Node(4L, 2L));
		list.add(new Node(5L, 2L));
		list.add(new Node(6L, 3L));
		
		//创建JSON处理器
		GsonBuilder gsonbuilder = new GsonBuilder().serializeNulls(); 
		Gson gson = gsonbuilder.create();
		
		Node root = buildTree(list, gson);
		
		System.out.println("tree: "+ gson.toJson(root));
	}
	
	static Node buildTree(List<Node> list, Gson gson){
		Map<Long, Node> map = new HashMap<Long, Node>();
		for(Node node : list){
			//把所有节点放进map中, id作为key
			map.put(node.getId(), node);
		}
		System.out.println("map1: "+ gson.toJson(map));

        //将节点加入对应父节点的children中
        //因为每个节点的父节点有且只有一个
		for(Entry<Long, Node> entry : map.entrySet()){
			Node currNode = entry.getValue();
			Node parentNode = map.get(currNode.getPid());
			if(parentNode != null){
				parentNode.addToChildren(currNode);
			}
		}
		System.out.println("map2: "+ gson.toJson(map));
		return map.get(1L);
	}
	
	//节点定义
    static class Node{
		private Long id;//id
		private Long pid;//父id
		private List<Node> children;//子节点集合
		
		public Node(){}
		public Node(Long id, Long pid){
			this.id = id;
			this.pid = pid;
		}
		
		public Long getId(){
			return this.id;
		}
		public Long getPid(){
			return this.pid;
		}
		
		public void addToChildren(Node node){
			if(this.children==null){
				this.children = new ArrayList<Node>();
			}
			this.children.add(node);
		}
	}
}
2.输出结果:

map1:

{
    "1":{
        "id":1,
        "pid":null,
        "children":null
    },
    "2":{
        "id":2,
        "pid":1,
        "children":null
    },
    "3":{
        "id":3,
        "pid":1,
        "children":null
    },
    "4":{
        "id":4,
        "pid":2,
        "children":null
    },
    "5":{
        "id":5,
        "pid":2,
        "children":null
    },
    "6":{
        "id":6,
        "pid":3,
        "children":null
    }
}

map2:

{
    "1":{
        "id":1,
        "pid":null,
        "children":[
            {
                "id":2,
                "pid":1,
                "children":[
                    {
                        "id":4,
                        "pid":2,
                        "children":null
                    },
                    {
                        "id":5,
                        "pid":2,
                        "children":null
                    }
                ]
            },
            {
                "id":3,
                "pid":1,
                "children":[
                    {
                        "id":6,
                        "pid":3,
                        "children":null
                    }
                ]
            }
        ]
    },
    "2":{
        "id":2,
        "pid":1,
        "children":[
            {
                "id":4,
                "pid":2,
                "children":null
            },
            {
                "id":5,
                "pid":2,
                "children":null
            }
        ]
    },
    "3":{
        "id":3,
        "pid":1,
        "children":[
            {
                "id":6,
                "pid":3,
                "children":null
            }
        ]
    },
    "4":{
        "id":4,
        "pid":2,
        "children":null
    },
    "5":{
        "id":5,
        "pid":2,
        "children":null
    },
    "6":{
        "id":6,
        "pid":3,
        "children":null
    }
}

tree:

{
    "id":1,
    "pid":null,
    "children":[
        {
            "id":2,
            "pid":1,
            "children":[
                {
                    "id":4,
                    "pid":2,
                    "children":null
                },
                {
                    "id":5,
                    "pid":2,
                    "children":null
                }
            ]
        },
        {
            "id":3,
            "pid":1,
            "children":[
                {
                    "id":6,
                    "pid":3,
                    "children":null
                }
            ]
        }
    ]
}
3.另一种写法(单次遍历)
package com.hello.test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class ArrToTreeV2 {
	public static void main(String[] args){
	    //设置初始数据(对顺序没有要求)
		List<Item> list = new ArrayList<Item>();
		list.add(new Item(6L, 3L));
		list.add(new Item(5L, 2L));
		list.add(new Item(4L, 2L));
		list.add(new Item(3L, 1L));
		list.add(new Item(2L, 1L));
		list.add(new Item(1L, null));//pid可以是null也可以是-1等不存在的id
		
		//创建JSON处理器
		GsonBuilder gsonbuilder = new GsonBuilder().serializeNulls(); 
		Gson gson = gsonbuilder.create();
		
		Node root = list2tree(list);
		
		System.out.println(gson.toJson(root));
	}
	
	static Node list2tree(List<Item> list){
		if(list==null || list.isEmpty()){
			return null;
		}
		
		Map<Long, Node> map = new HashMap<Long, Node>();
		for(Item item : list){
			//1.加入当前节点
			Long id = item.getId();
			Node currNode = map.get(id);
			if(currNode == null){
				currNode = new Node(item);
				map.put(id, currNode);
			}else{//被别的节点以父节点加入
				currNode.setByItem(item);
			}
			
			//2.把当前节点加入父节点的children
			Long pid = item.getPid();
			Node parentNode = map.get(pid);
			if(parentNode == null){//父节点不存在则临时创建一个
				parentNode = new Node(pid);
				parentNode.addToChildren(currNode);
				map.put(pid, parentNode);
			}else{//已存在父节点,直接加入他的children
				parentNode.addToChildren(currNode);
			}
		}
		return map.get(null);
	}
	
	static class Item{
		private Long id;//id
		private Long pid;//父id
		//other fields...
		
		public Item(){}
		public Item(Long id, Long pid){
			this.id = id;
			this.pid = pid;
		}
		
		public void setId(Long id) {
			this.id = id;
		}
		public void setPid(Long pid) {
			this.pid = pid;
		}
		public Long getId() {
			return id;
		}
		public Long getPid() {
			return pid;
		}
	}
	
	//节点定义
    static class Node{
		private Long id;//id
		private Long pid;//父id
		private List<Node> children;//子节点集合
		
		public Node(){}
		public Node(Item item){
			this.id = item.getId();
			this.pid = item.getPid();
		}
		public Node(Long id){
			this.id = id;
		}
		
		public void setByItem(Item item) {
			//在这里复制id,children以外的所有属性值
			this.pid = item.getPid();
		}
		public Long getId(){
			return this.id;
		}
		public Long getPid(){
			return this.pid;
		}
		
		public void addToChildren(Node node){
			if(this.children==null){
				this.children = new ArrayList<Node>();
			}
			this.children.add(node);
		}
	}
}

输出结果:

{
    "id":null,
    "pid":null,
    "children":[
        {
            "id":1,
            "pid":null,
            "children":[
                {
                    "id":3,
                    "pid":1,
                    "children":[
                        {
                            "id":6,
                            "pid":3,
                            "children":null
                        }
                    ]
                },
                {
                    "id":2,
                    "pid":1,
                    "children":[
                        {
                            "id":5,
                            "pid":2,
                            "children":null
                        },
                        {
                            "id":4,
                            "pid":2,
                            "children":null
                        }
                    ]
                }
            ]
        }
    ]
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值