列表转树结构,获取节点到根的路径

发布时间 2023-07-06 09:13:05作者: 豆苗稀

列表转树结构

逻辑上呈树结构的数据,诸如菜单,省市区,在数据库中单表存放,Java程序从数据库中读取出来这些数据时,是列表形式。列表转树结构使用双层for循环实现:

    /**
     * 节点组成树形结构,返回森林
     *
     * @param list      节点列表
     * @param predicate 定义树的根节点
     * @return 森林
     */
    static <T extends ITree<T>> List<T> toForest(List<T> list, Predicate<T> predicate) {
        for (T item : list) {
            List<T> children = list.stream()
                    .filter(c -> Objects.equals(c.getParentId(), item.getId()))
                    .collect(Collectors.toList());
            item.setChildren(children);
        }
        List<T> tree = list.stream().filter(predicate)
                .collect(Collectors.toList());
        return tree;
    }

获取节点至根的路径

使用递归的样例代码如下:

    /**
     * 例如 areaCode=130400时,返回河北省邯郸市
     * 例如 areaCode=130000时,返回河北省
     *
     * @param areaCode 省、市、区级编码
     * @return 从省级全名拼接到areaCode全名的路径
     */
    public String getPathFullname(String areaCode) {
        AreaDict areaDict = dao.findByAreaCode(areaCode).orElse(null);
        if (areaDict == null) return "";
        if (!COUNTRY_CODE.equals(areaDict.getParentCode())) {
            return getPathFullname(areaDict.getParentCode()) + areaDict.getFullname();
        }
        return areaDict.getFullname();
    }

可以优化为使用双层for循环,list保存中间的迭代结果的方式,替代递归。
伪代码:

function(areaCode){
  List list = new List();
  list.add(areaCode)
  while(list.tail is not root){
    list.add(parent(list.tail))
  }
  return list.reverse().join()
}