java - listmap组装树形结构

package cn.seaboot.commons.core;

import cn.seaboot.commons.exception.BizException;
import cn.seaboot.commons.lang.Warning;

import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 数据组装树形结构(Map版本)
 *
 * @author Mr.css
 * @version 2020-07-06 11:18
 */
public class TreeBuilder {
    private List<Map<String, Object>> parent;
    private List<Map<String, Object>> child;
    private String idField = "id";
    private String pidField = "pid";
    private String childrenField = "children";


    public List<Map<String, Object>> getParent() {
        return parent;
    }

    public TreeBuilder setParent(List<Map<String, Object>> parent) {
        this.parent = parent;
        return this;
    }

    public List<Map<String, Object>> getChild() {
        return child;
    }

    public TreeBuilder setChild(List<Map<String, Object>> child) {
        this.child = child;
        return this;
    }

    public TreeBuilder setIdField(String idField) {
        this.idField = idField;
        return this;
    }

    public TreeBuilder setPidField(String pidField) {
        this.pidField = pidField;
        return this;
    }

    public TreeBuilder setChildrenField(String childrenField) {
        this.childrenField = childrenField;
        return this;
    }

    /**
     * 数据分组
     *
     * @return TreeBuilder
     */
    @SuppressWarnings(Warning.UNCHECKED)
    public TreeBuilder groupBy() {
        if (child == null) {
            child = parent;
        }
        for (Map<String, Object> p : parent) {
            for (Map<String, Object> c : child) {
                if (p.get(this.idField).equals(c.get(this.pidField))) {
                    List<Map<String, Object>> list = (List<Map<String, Object>>) p.get(this.childrenField);
                    if (list == null) {
                        list = new ArrayList<>();
                        p.put(this.childrenField, list);
                    }
                    list.add(c);
                }
            }
        }
        return this;
    }

    /**
     * 如果已知要取的节点,直接按照节点pId进行获取
     *
     * @return tree
     */
    public List<Map<String, Object>> getByPid(@Nullable Object pidValue) {
        List<Map<String, Object>> res = new ArrayList<>();
        if (pidValue == null) {
            for (Map<String, Object> p : parent) {
                if (p.get(pidField) == null) {
                    res.add(p);
                }
            }
        } else {
            for (Map<String, Object> p : parent) {
                if (p.get(pidField).equals(pidValue)) {
                    res.add(p);
                }
            }
        }
        return res;
    }

    /**
     * 从组装的结果中取出Pid最小的数据
     *
     * @return tree
     */
    @SuppressWarnings({Warning.UNCHECKED, Warning.RAW_TYPES})
    public List<Map<String, Object>> getByMinPid() {
        Comparable min = (Comparable) parent.get(0).get(pidField);
        Comparable obj;
        for (Map<String, Object> p : parent) {
            obj = (Comparable) p.get(pidField);
            if (obj.compareTo(min) < 0) {
                min = obj;
            }
        }
        return this.getByPid(min);
    }

    /**
     * 从组装的结果中取出Pid最大的数据
     *
     * @return tree
     * @throws ClassCastException List元素未继承自Comparable接口
     */
    @SuppressWarnings({Warning.UNCHECKED, Warning.RAW_TYPES})
    public List<Map<String, Object>> getByMaxPid() {
        Comparable max = (Comparable) parent.get(0).get(pidField);
        Comparable obj;
        for (Map<String, Object> p : parent) {
            obj = (Comparable) p.get(pidField);
            if (obj.compareTo(max) > 0) {
                max = obj;
            }
        }
        return this.getByPid(max);
    }

    /**
     * 随机取出一个元素,反复遍历树,直到取出最顶级的父节点
     *
     * @return tree
     * @throws ClassCastException List元素未继承自Comparable接口
     */
    @SuppressWarnings({Warning.UNCHECKED, Warning.RAW_TYPES})
    public List<Map<String, Object>> getRoot() {
        // 存在 pid 为 null 的数据
        for (Map<String, Object> p : parent) {
            if (p.get(pidField) == null) {
                return this.getByPid(null);
            }
        }

        Comparable max = (Comparable) parent.get(0).get(pidField);

        // 已经查找过的节点
        List<Comparable> list = new ArrayList<>();
        while (true) {
            // 查找更大的父节点
            Comparable pid = null;
            for (Map<String, Object> p : parent) {
                if (max.compareTo(p.get(idField)) == 0) {
                    pid = (Comparable) p.get(pidField);
                    break;
                }
            }

            if (pid == null) {
                // 找不到更大的节点,与 for 循环中的空值判断含义不同
                return this.getByPid(max);
            } else {
                max = pid;
                // 判断是否发生循环依赖,不然会发生无线循环
                if (list.contains(max)) {
                    throw new BizException("Circular dependencies");
                } else {
                    list.add(max);
                }
            }
        }
    }
}


posted on 2019-07-02 17:46  疯狂的妞妞  阅读(652)  评论(0编辑  收藏  举报

导航