菜单树Java实现

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

import com.alibaba.fastjson.JSONObject;

/**
 * 描述:简单树型结构,一定要正确构建,否则容易陷入死循环
 *
 * @author jianlin.zhu
 * @create 2019-03-28 13:49
 **/
public class Tree<K,T> implements Serializable {
    private K key;
    private T data;
    private List<Tree<K, T>> children = new ArrayList<>();
    private K parent;
    private int level;

    public Tree(K key, T data) {
        this.key = key;
        this.data = data;
        this.parent = null;

    }

    public Tree(K key, T data, K parent, int level) {
        this.key = key;
        this.data = data;
        this.parent = parent;
        this.level = level;
    }

    public boolean isRoot() {
        return parent == null;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }


    public List<Tree<K, T>> getChildren() {
        return children;
    }

    public void setChildren(List<Tree<K, T>> children) {
        this.children = children;
    }

    public K getParent() {
        return parent;
    }

    public void setParent(K parent) {
        this.parent = parent;
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }


    public K getKey() {
        return key;
    }

    public void setKey(K key) {
        this.key = key;
    }

    /**
     * 是否为叶子节点,根节点不算
     * @return
     */
    public boolean isLeaf() {
        return !isRoot() && this.getChildren().size()==0;
    }

    @Override
    public String toString() {
        return JSONObject.toJSONString(this);
    }

    public  Tree<K,T> findByKey(K key){
        Tree<K,T> root = this;
        if(root.key.equals(key)){
            return  root;
        }

        if(root.getChildren().size()>0){
            for(Tree<K,T> child : root.getChildren() ){
                Tree<K,T> a = child.findByKey(key);
                if(a != null){
                    return  a;
                }
            }
        }
        return  null;
    }



    public List<Tree<K,T> > asList(){
        List<Tree<K,T>> trees = new ArrayList<>();
        Tree<K,T> root = this;
        trees.add(root);
        for(Tree<K,T> child : root.getChildren() ){
            trees.addAll(child.asList());
        }
        return trees;
    }

    public List<Tree<K,T> > asListWithoutChildren(){
        List<Tree<K,T> > result = new ArrayList<>();
        List<Tree<K,T> > list = asList();
        for(Tree<K,T> item:list){
            result.add(new Tree<>(item.getKey(),item.getData(),item.getParent(),item.getLevel()));
        }
        return result;
    }


    public Tree<K,T> removeNode(K key){
        Tree<K,T> _node = null;
        if( (_node = findByKey(key))!=null ){
            if(_node.getParent() != null){
                Tree<K,T> parent =  findByKey(_node.getParent());
                if(parent != null){
                    if(parent.getChildren().remove(_node)){
                        return _node;
                    }
                }
            }
        }
        return _node;
    }
    public static <K, T>  Tree<K, T> buildFrom(List<Tree<K, T>> list) {
        Tree<K, T> root = null;
        for (Tree<K, T> node : list) {
            if(node.getParent() == null){
                root = node;
                break;
            }
        }

        for (Tree<K, T> node : list) {
            if(node.getParent() == null){
                continue;
            }
            Tree<K, T> parent = root.findByKey(node.getParent());
            parent.getChildren().add(node);
        }

        return root;

    }

 /**
     * 后根顺遍历
     * @param tree
     * @param visitor
     * @param <K>
     * @param <T>
     */
    public static <K, T> List<Object> postOrder(Tree<K, T> tree, Visitor<K,T> visitor){
         List<Object> result = new ArrayList<>();
         if(tree != null){
             result.addAll(postOrder(tree.getChildren().size()==0?null:tree.getChildren().get(0),visitor));// left
             if(tree.getChildren().size()>1){ //right
                 for(int i=1;i<tree.getChildren().size();++i){
                     result.addAll(postOrder(tree.getChildren().get(i),visitor));
                 }
             }
             // visit root
             Object obj= visitor.handle(tree.getKey(),tree.getData(),tree.getParent(),tree.getLevel(),tree);
             if(obj !=null ){
                 result.add(obj);
             }
         }

         return result;

    }

}


public interface Visitor<K,T> {
     Object handle(K key, T data, K parent, int level,Tree<K, T> cur);
}


import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import org.junit.Test;


public class TreeTest extends FastBaseTest{

    @Test
    public void test(){
        Long ROOT_KEY = 0L;
        Tree<Long, MenuVO> root = new Tree<>(ROOT_KEY, null, null, 0);
        Tree<Long, MenuVO> first1 = new Tree<>(1L, new MenuVO(1L,"/page1","",0L,1,1), ROOT_KEY, 1);
        Tree<Long, MenuVO> first2 = new Tree<>(2L, new MenuVO(2L,"/page2","",0L,2,1), ROOT_KEY, 1);
        Tree<Long, MenuVO> second1 = new Tree<>(21L, new MenuVO(11L,"/page1/init","",1L,1,1), 1L, 1);
        Tree<Long, MenuVO> second2 = new Tree<>(22L, new MenuVO(12L,"/page1/main","",1L,1,1), 1L, 1);

        Tree<Long, MenuVO> myTree = Tree.buildFrom(Lists.newArrayList(root,first1,first2,second1,second2));
//        等价于
//        root.getChildren().add(first1);
//        root.getChildren().add(first2);
//        first1.getChildren().add(second1);
//        first1.getChildren().add(second2);

        print(myTree,true);

        // 打印每一个节点
        myTree.asListWithoutChildren().forEach(a->{
            print(a,true);
        });

        // 序列化树
        String treeStr = JSONObject.toJSONString(myTree);
        print(treeStr,true);

        // 反序列化树,还不能还原!
        Tree<Long,MenuVO> tree = JSONObject.parseObject(treeStr,Tree.class);
        print(tree,true);

    }

 public void testPostOrder( Tree<Long, MenuVO> root){
        List<Object> result = Tree.postOrder(root, new Visitor<Long, MenuVO>() {
            @Override
            public Object handle(Long aLong, MenuVO data,Long parent,int level,Tree<Long, MenuVO> cur) {
                System.out.println(data==null?"root":data.getUri());
                return data==null?"root":data.getUri();
            }
        });

        String treeStr = JSONObject.toJSONString(result);
        print(treeStr,true);
    }

}
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ExecutorService;


public class FastBaseTest {
    protected Logger logger = LoggerFactory.getLogger(getClass());

    protected void print(Object obj, boolean isPretty, Object... params) {
        logger.info(JSONObject.toJSONString(obj, isPretty));
        if (params != null) {
            for (Object param : params) {
                logger.info(JSONObject.toJSONString(param, isPretty));
            }
        }
    }

    public static void waitClose(ExecutorService executorService) {
        executorService.shutdown();
        while(!executorService.isTerminated()){
            try {
                Thread.sleep(100);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;


@Data
@NoArgsConstructor
@AllArgsConstructor
public class MenuVO implements Serializable {

    private Long id;
    private String uri;
    private String name;
    private Long pid;
    private Integer order;
    private Integer level;
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值