几行代码搞定任意java对象集合转换为树形对象和常见tree查找操作

3 篇文章 0 订阅

      开发过程中经常遇到tree结构的数据,如果是继承,那么就耦合了,  有了这个工具类,几行代码搞定常见tree查找操作

     下面代码实现了任意对象的tree结构化封装,也可以是多组tree,与原对象解耦,未使用递推算法,包含了常见的对象级别,对象父节点,子节点遍历,查找方法,向上查找和向下查找,应有尽有,开箱即用.方法可能写的比较冗余,请自行精炼优化,轻喷.

     性能和存储如有问题,欢迎下方给我留言.hashMap 初始化大小/0.75 = 设置大小

代码如下:

首先创建一个Node节点对象

 

package com.wzy.demo.node;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.apache.commons.collections.CollectionUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description:
 * @Date: 2020/7/30 17:52
 * @Author:wzy
 * @Modified:
 **/
@Setter
@Getter
@NoArgsConstructor
public class Node<T> implements Serializable {

    private static final long serialVersionUID = 1L;
    private String id;//id
    private String pId;//父id
    private String rootId;

    private T value;

    private List<Node<T>> childs = new ArrayList<>();
    /**id**/
    private List<String> parents = new ArrayList<>();

    private Integer level;

    public Node(String id, String pId) {
        this.id = id;
        this.pId = pId;
    }

    public Node(String id, String pId, T value) {
        this.id = id;
        this.pId = pId;
        this.value = value;
    }
    public boolean haveChilds(){
        return CollectionUtils.isNotEmpty(childs);
    }
}

对象工具类

package com.wzy.demo.node;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Date: 2020/7/30 17:52
 * @Author:wzy
 * @Modified:
 **/
@Slf4j
public class NodeUtil<T> {

    private final Map<String, Node<T>> mapNode = new HashMap<>();
    private List<Node<T>> allNodes = new ArrayList<>();
    private Node<T> nodeTree;
    private boolean isAreadyUnboxing;

    private NodeUtil() {
    }

    /**
     * 已初始化
     *
     * @param allNodes
     */
    public NodeUtil(List<Node<T>> allNodes) {
        this.allNodes = allNodes;
        for (Node<T> node : allNodes) {
            mapNode.put(node.getId(), node);
        }
        nodeTree = this.getTree();
    }

    /**
     * 查找集合的所有根节点,不包含子节点
     *
     * @param <T>
     * @return
     */
    public <T> List<Node<T>> findRoots() {
        List<Node<T>> results = new ArrayList();
        for (Node node : allNodes) {
            boolean isRoot = true;
            for (Node comparedOne : allNodes) {
                if (StringUtils.equals(node.getPId(), comparedOne.getId())) {
                    isRoot = false;
                    break;
                }
            }
            if (isRoot) {
                //node.setLevel(0);
                results.add(node);
                node.setRootId(node.getId());
            }
        }
        return results;
    }
 

 

测试bean

package com.wzy.demo;
import lombok.Getter;
import lombok.Setter;

import java.util.List;

/**
 *
 @Description:
 @Date: 2020/10/17 22:43
 @Author:wzy
 @Modified:
 **/
@Getter
@Setter
public class TestTreeNodeBean {
    private String id;
    private String pid;
    private String name;

    private List<TestTreeNodeBean> children;
    private Integer level;

    public TestTreeNodeBean(String id, String pid, String name) {
        this.id = id;
        this.pid = pid;
        this.name = name;
    }
}

测试工具类

package com.wzy.demo;


import com.alibaba.fastjson.JSON;
import com.wzy.demo.node.Node;
import com.wzy.demo.node.NodeUtil;
import lombok.extern.slf4j.Slf4j;
import net.minidev.json.JSONArray;
import org.apache.commons.collections.CollectionUtils;
import org.junit.jupiter.api.Test;

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

/**
 * @Description:
 * @Date: 2020/10/17 22:32
 * @Author:wzy
 * @Modified:
 **/
@Slf4j
public class TestNode {
    @Test
    public void s2() {
        TestTreeNodeBean beanRoot =new TestTreeNodeBean("0","-1","根目录");
        TestTreeNodeBean child1 =new TestTreeNodeBean("1","0","根目录");
        TestTreeNodeBean child2 =new TestTreeNodeBean("2","0","根目录");
        TestTreeNodeBean child3 =new TestTreeNodeBean("3","1","根目录");
        TestTreeNodeBean child4 =new TestTreeNodeBean("4","1","根目录");
        TestTreeNodeBean child6 =new TestTreeNodeBean("6","1","根目录");
        TestTreeNodeBean child7 =new TestTreeNodeBean("7","6","根目录");
        TestTreeNodeBean child5 =new TestTreeNodeBean("5","2","根目录");

        List<TestTreeNodeBean> originalDate = new ArrayList<TestTreeNodeBean>(){
            {
                add(beanRoot); add(child1); add(child2); add(child3); add(child4); add(child5);
                add(child6);add(child7);
            }
        };
        List<Node<TestTreeNodeBean>> allNodes;

        allNodes = originalDate.stream().map(s -> new Node<>(s.getId(), s.getPid(), s)).collect(Collectors.toList());


        NodeUtil<TestTreeNodeBean> tree = new NodeUtil<>(allNodes);
        this.unBoxingDate(tree);
        log.info("tree:[{}]", JSON.toJSONString(tree));
        log.info("tree:[{}]", JSON.toJSONString(tree.getAllParentNode(tree.getMapNode().get(child7.getId()))));
        log.info("end:[{}]", "no thing");




    }
    @Test
    private void s1() {
        List<Node<String>> allNodes = new ArrayList<>();
        Node<String> nodeTest = new Node<>("9", "8", "你10");
        Node<String> node4 = new Node<String>("4", "1", "你5");
        allNodes.add(new Node<>("-1", "9999", "你1"));

        allNodes.add(new Node<>("1", "0", "你2"));
        allNodes.add(new Node<>("2", "0", "你3"));
        allNodes.add(new Node<>("3", "0", "你4"));
        allNodes.add(node4);
        allNodes.add(new Node<>("5", "1", "你6"));
        allNodes.add(new Node<>("6", "2", "你7"));
        allNodes.add(new Node<>("7", "2", "你8"));
        allNodes.add(new Node<>("8", "4", "你9"));
        allNodes.add(nodeTest);
        allNodes.add(new Node<>("10", "8", "你11"));

        NodeUtil<String> util = new NodeUtil<>(allNodes);
        List<Node<String>> values = new ArrayList<>();
        values = util.findRoots();

        Node<String> nodeTree = util.getNodeTree();

        for (Node<String> child : nodeTree.getChilds()) {
            int levelInt = util.getNodeLevel(nodeTree, nodeTest);
            log.info("node level:[{}][{}]", child.getValue(), levelInt);
        }
        List<Node<String>> parentNodes = util.getAllParentNode(nodeTest);
        StringBuffer sb = new StringBuffer();
        parentNodes.forEach(s -> {
            sb.append(s.getValue()).append("/");
        });
        //sb =你2/你5/你9/  这里拿到了所有的父节点
        List<Node<String>> childNodes = util.getAllChildNode(util.getMapNode().get(node4.getId()));

        log.info("childNodes:[{}]", JSONArray.toJSONString(childNodes));
    }

    /**
     * 如果是对象,例如有id,pid, List<T>  children; 三个参数,
     * 当创建nodeTree后,其实原始对象里这些数据还没有值,所以这里做一步赋值操作
     * 其实这里应该可以用反射做,比较通用
     *
     * @param
     */
    private void unBoxingDate(NodeUtil<TestTreeNodeBean> nodeUtil) {

        if (nodeUtil.isAreadyUnboxing()) {
            return;
        }
        nodeUtil.setAreadyUnboxing(true);
        Node<TestTreeNodeBean> categoryNode = nodeUtil.getNodeTree();
        List<Node<TestTreeNodeBean>> temp = new ArrayList<>();
        temp.add(categoryNode);
        do {
            for (Node<TestTreeNodeBean> tree : temp) {
                if (tree.getValue() == null) {
                    //tree.setValue(new CategoryBean());
                    continue;
                }
                if (tree.getValue().getChildren() == null) {
                    tree.getValue().setChildren(new ArrayList<>());
                }
                if (CollectionUtils.isEmpty(tree.getChilds())) {
                    return;
                }
                for (Node<TestTreeNodeBean> child : tree.getChilds()) {
                    if (tree.getValue().getLevel() == null) {
                        tree.getValue().setLevel(tree.getLevel());
                    }
                    child.getValue().setLevel(child.getLevel());
                    tree.getValue().getChildren().add(child.getValue());

                }
            }
            temp = temp.stream().flatMap(s -> s.getChilds().stream()).collect(Collectors.toList());
        } while (org.apache.commons.collections.CollectionUtils.isNotEmpty(temp));


    }
}

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值