递归调用转为循环

天大地大妈咪最大 提交于 2020-02-22 05:35:21

背景

有一个接口会返回json格式的字符串,json格式是嵌套的,类似这样的如下的结构,需要转换为一个list,当然最简单的写一个递归就可以了,但是有一句话: “所有的递归都可以转化为循环”,那么就练练自己的代码能力,温故而知新,用循环实现吧。

{
	"respData":[
		{
			"id":1,
			"isvalid":1,
			"orgName":"汽车",
			"parentId":0,
			"subOrgList":[
				{
					"id":33,
					"isvalid":1,
					"orgName":"客车",
					"parentId":1,
					"subOrgList":[
						{
							"id":37,
							"isvalid":1,
							"orgName":"大客车",
							"parentId":33
						},
						{
							"id":38,
							"isvalid":1,
							"orgName":"小客车",
							"parentId":33
						}
					]
				},
				{
					"id":88,
					"isvalid":1,
					"orgName":"SUV",
					"parentId":1
				}
			]
		},
		{
			"id":2,
			"isvalid":1,
			"orgName":"自行车",
			"parentId":0,
			"subOrgList":[
				{
					"id":56,
					"isvalid":1,
					"orgName":"永久",
					"parentId":2
				}
			]
		},
		{
			"id":4,
			"isvalid":1,
			"orgName":"地铁",
			"parentId":0
		}
	],
	"respCode":"0"
}

原理

假如有如下图所示的json结构字符串,整个结构为jsonArray,蓝色框中的时jsonArray1,红色框中的时jsonArray2,jsonArray1中有jsonArray11和jsonArray12,jsonArray11中有jsonArray111。
在这里插入图片描述
栈为先入后出

  1. 第一次循环:把1、2、3、4、5、6、7、8的节点信息放到结果list中,并把jsonArray1、jsonArray2放到栈中;
  2. 第二次循环:循环jsonArray2,把711、712放入结果list中;
  3. 第三次循环:循环jsonArray1,把jsonArray11和jsonArray12放入栈中;
  4. 第四次循环:jsonArray12,把121、122放入结果list中;
  5. 第五次循环:循环jsonArray11,把111、112、113、114放到结果list中,jsonArray111放入栈中;
  6. 第六次循环:循环jsonArray111,把1111、1112放入结果list中。

代码

public class SelectionEntity {
    private String id;
    private String text;

    public SelectionEntity(String id, String text) {
        this.id = id;
        this.text = text;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    @Override
    public String toString() {
        return "SelectionEntity{" +
                "id='" + id + '\'' +
                ", text='" + text + '\'' +
                '}';
    }
}
public List<SelectionEntity> companyAll() {
    List<SelectionEntity> selectionEntities = new ArrayList<>();

    loggerHelper.info("接口返回成功,开始转换");
    // 省略了获取json格式内容的调用
    String content = "{\"respData\":[{\"id\":1,\"isvalid\":1,\"orgName\":\"汽车\",\"parentId\":0,\"subOrgList\":[{\"id\":33,\"isvalid\":1,\"orgName\":\"客车\",\"parentId\":1,\"subOrgList\":[{\"id\":37,\"isvalid\":1,\"orgName\":\"大客车\",\"parentId\":33},{\"id\":38,\"isvalid\":1,\"orgName\":\"小客车\",\"parentId\":33}]},{\"id\":88,\"isvalid\":1,\"orgName\":\"SUV\",\"parentId\":1}]},{\"id\":2,\"isvalid\":1,\"orgName\":\"自行车\",\"parentId\":0,\"subOrgList\":[{\"id\":56,\"isvalid\":1,\"orgName\":\"永久\",\"parentId\":2}]},{\"id\":4,\"isvalid\":1,\"orgName\":\"地铁\",\"parentId\":0}],\"respCode\":\"0\"}";
    JSONObject jsonObject = JSONObject.parseObject(content);
    
    JSONArray jsonArray = jsonObject.getJSONArray("respData");
    String hasSubOrgKey = "subOrgList";
    Stack<TreeStruct> structStack = new Stack<>();
    
    // 当前jsonArray放入栈中
    structStack.push(new TreeStruct("", jsonArray));
    do {
        // 从栈中获取
        TreeStruct struct = structStack.pop();
        String parentName = struct.getCurrentName();
        // 遍历jsonArray
        for (int i = 0, jsonArray = struct.getJsonArray(); i < jsonArray.size(); i++) {
            JSONObject jsonObject1 = jsonArray.getJSONObject(i);
    
            // 当前对象的名称由父节点名称和当前节点名称拼装而成
            String name = jsonObject1.getString("orgName");
            if (!parentName.isEmpty()) {
                name = String.join("-", parentName, name);
            }
    
           // 如果当前节点有 子列表
            if (jsonObject1.containsKey(hasSubOrgKey) && jsonObject1.getJSONArray(hasSubOrgKey).size() > 0) {
                // 子列表放入栈中
                structStack.push(new TreeStruct(name, jsonObject1.getJSONArray(hasSubOrgKey)));
            }
    
            String orgId = jsonObject1.getString("id");
            // 当前对象放入结果list中
            selectionEntities.add(new SelectionEntity(orgId, name));
        }
    // 当前栈中有内容就继续循环
    } while (!structStack.empty());
    
    loggerHelper.info("转换完成,size:", selectionEntities.size());

    return selectionEntities;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!