listmap

2023/4/7

# 1 对象List转为Tree树形结构

public final List<Map<String, Object>> listToTree(List<Map<String, Object>> entityList, String primaryFieldName, String parentFieldName) {
        //返回的map Tree树形结构
        List<Map<String, Object>> treeMap = new ArrayList<>();
        //将传进的参数entityList转为MapList
        List<Map<String, Object>> listMap = JSON.parseObject(JSON.toJSONString(entityList), List.class);
        //声明一个map用来存listMap中的对象,key为对象id,value为对象本身
        Map<String, Map<String, Object>> entityMap = new Hashtable<>();
        //循环listMap把map对象put到entityMap中去
        listMap.forEach(map -> entityMap.put(map.get(primaryFieldName).toString(), map));
        //循环listMap进行Tree树形结构组装
        listMap.forEach(map -> {
            //获取map的pid
            Object pid = map.get(parentFieldName);
            //判断pid是否为空或者为0,为空说明是最顶级,直接add到返回的treeMap中去
            if (pid == null || StringUtils.equals(pid.toString(), String.valueOf(1))) {
                treeMap.add(map);
            } else {
                //如果pid不为空也不为0,是子集
                // 根据当前map的pid获取上级 parentMap
                Map<String, Object> parentMap = entityMap.get(pid.toString());
                if (parentMap == null) { //如果parentMap为空,则说明当前map没有父级,当前map就是顶级
                    treeMap.add(map);
                } else {
                    //如果parentMap不为空,则当前map为parentMap的子级
                    //取出parentMap的所有子级的List集合
                    List<Map<String, Object>> children = (List<Map<String, Object>>) parentMap.get(CHILDREN);
                    if (children == null) {  //判断子级集合是否为空,为空则新创建List
                        children = new ArrayList<>();
                        parentMap.put(CHILDREN, children);
                    }
                    //把当前map对象add到parentMap的子级List中去
                    children.add(map);
                    /**
                     * 因为parentMap是从entityMap中get出来的,
                     * 而entityMap中的value又是来自于listMap对象,
                     * 所以parentMap和entityMap中的value的地址都是指向listMap中的对象,
                     * 所以parentMap的children和entityMap中的value的children改变时,都会改变listMap中的对象,
                     */
                }
            }
        });
        return treeMap;
    }

# 2 List To map

List<Map<String, Object>> param //这是一个有children子节点的集合,每一个节点都是一个map

//创建一个新的list map
List<Map<String, Object>> newList = new ArrayList<>();

//遍历param里面的每一个map
for (Map<String, Object> map : param) {
    //创建一个新的map来存储数据
    Map<String, Object> newMap = new HashMap<>();

    //把map里面的键值对复制到新的map中
    newMap.putAll(map);

    //判断是否有children这个键
    if (newMap.containsKey("children")) {
        //获取children对应的值(一个List<Map<String, Object>>)
        try {

            List<Map<String, Object>> children = (List<Map<String, Object>>) newMap.get("children");

            //遍历children里面的每一个子map
            for (Map<String, Object> child : children) {
                //创建一个新的子map来存储数据
                Map<String, Object> newChild = new HashMap<>();

                //把子map里面的键值对复制到新的子map中
                newChild.putAll(child);

                //把新的子map添加到新的list中
                newList.add(newChild);
            }

            //从新的map中移除children这个键,因为它已经被处理过了
            newMap.remove("children");
        } catch (ClassCastException e) {
            log.error(e.getMessage());
            //抛出新的自定义异常
            throw new MyException(e.getMessage() + "输入类型格式错误");
        }
    }

    //把新的map添加到新的list中
    newList.add(newMap);
}

# 3 buildTree v1 v2版本


package com.example.community.stream;

import com.example.community.model.entity.Tree;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author: lichengcan
 * @date: 2023-07-28 17:00
 * @description buildTree
 **/
public class TreeStreamTest {

    public static List<Tree> createTreeList() {
        List<Tree> TreeList = new ArrayList<>();
        TreeList.add(new Tree("f", "e", "fff"));
        TreeList.add(new Tree("a", "0", "lcc"));
        TreeList.add(new Tree("b", "0", "bbb"));
        TreeList.add(new Tree("c", "0", "ccc"));
        TreeList.add(new Tree("h", "g", "hhhhh"));
        TreeList.add(new Tree("d", "a", "ddd"));
        TreeList.add(new Tree("e", "b", "eee"));
        TreeList.add(new Tree("g", "e", "fff"));
        TreeList.add(new Tree("i", "x", "iiii"));
        return TreeList;
    }

    public static void main(String[] args) {
        //初始化数据
        List<Tree> treeList = createTreeList();
        //获取根节点
        List<Tree> trees = getRoot(treeList);
        System.out.println("trees = " + trees);
        //构建树v2版本
        buildTreeV2(treeList);
    }

    public static List<Tree> getRoot(List<Tree> trees) {
        List<Tree> roots = trees.stream().filter(x -> x.getParentId().equals("0")).collect(Collectors.toList());
        //构建树形结构
        roots.stream().forEach(root -> buildTreeV1(root, trees));
        //只保留根节点对象
        return trees.stream().filter(tree -> tree.getParentId().equals("0")).collect(Collectors.toList());
    }

    public static void buildTreeV1(Tree root, List<Tree> trees) {
        trees.stream()
                .forEach(tree -> {
                    if (tree.getParentId().equals(root.getId())) {
                        if (root.getChild() == null) {
                            root.setChild(new ArrayList<>());
                        }
                        root.getChild().add(tree);
                        //把当前节点和整个数组重新
                        buildTreeV1(tree, trees);
                    }
                });
    }

    public static List<Tree> buildTreeV2(List<Tree> trees) {
        //将List转换成map,id作为key可以更方便的拿到父节点、子节点,减少了重复扫描整个列表,降低了时间复杂度
        Map<String, Tree> treeMap = trees.stream().collect(Collectors.toMap(Tree::getId, t -> t));
        //开始构建树
        List<Tree> roots = new ArrayList<>();
        trees.stream().forEach(tree -> {
            //当前节点的爸爸id
            String parentId = tree.getParentId();
            //是不是老大
            if ("0".equals(parentId)) {
                roots.add(tree);
            } else {
                //不是老大
                //拿到爸爸
                Tree parent = treeMap.get(parentId);
                //爸爸没有儿子
                if (parent != null) {
                    //初始化空儿子
                    if (parent.getChild() == null) {
                        parent.setChild(new ArrayList<>());
                    }
                    //给他一个亲生儿子
                    parent.getChild().add(tree);
                }
            }
        });
        return roots;
    }
}