递归树使用的一个场景

参考链接:https://www.cnblogs.com/lucky-pin/p/10740037.html

聊一下我遇到的场景哈,为啥突然要用到这个递归树了呢?

是因为项目中的一个目录树的查询操作,当目录很多的时候,代码中频繁递归查询数据库,和数据库交互次数过多。
后来就想先把所有数据查询出来,构建出树结构,减少和数据库的交互次数

import java.util.ArrayList;
import java.util.List;

public class MenuTree {
    private List<Menu> menuList = new ArrayList<Menu>();
    public MenuTree(List<Menu> menuList) {
        this.menuList=menuList;
    }

    //建立树形结构
    public List<Menu> builTree(){
        List<Menu> treeMenus =new  ArrayList<Menu>();
        for(Menu menuNode : getRootNode()) {
            menuNode=buildChilTree(menuNode);
            treeMenus.add(menuNode);
        }
        return treeMenus;
    }

    //递归,建立子树形结构
    private Menu buildChilTree(Menu pNode){
        List<Menu> chilMenus =new  ArrayList<Menu>();
        for(Menu menuNode : menuList) {
            if(menuNode.getParentId().equals(pNode.getId())) {
                chilMenus.add(buildChilTree(menuNode));
            }
        }
        pNode.setChildren(chilMenus);
        return pNode;
    }

    //获取根节点
    private List<Menu> getRootNode() {
        List<Menu> rootMenuLists =new  ArrayList<Menu>();
        for(Menu menuNode : menuList) {
            if(menuNode.getParentId().equals("0")) {
                rootMenuLists.add(menuNode);
            }
        }
        return rootMenuLists;
    }
}
import java.util.ArrayList;
import java.util.List;
import com.alibaba.fastjson.JSON;

public class Hello {
    public static void main(String []args) {
        List<Menu>  menuList= new ArrayList<Menu>();
        /*插入一些数据*/
        menuList.add(new Menu("GN001D000","0","系统管理","/admin","Y"));
        menuList.add(new Menu("GN001D100","GN001D000","权限管理","/admin","Y"));
        menuList.add(new Menu("GN001D110","GN001D100","密码修改","/admin","Y"));
        menuList.add(new Menu("GN001D120","GN001D100","新加用户","/admin","Y"));
        menuList.add(new Menu("GN001D200","GN001D000","系统监控","/admin","Y"));
        menuList.add(new Menu("GN001D210","GN001D200","在线用户","/admin","Y"));
        menuList.add(new Menu("GN002D000","0","订阅区","/admin","Y"));
        menuList.add(new Menu("GN003D000","0","未知领域","/admin","Y"));
        /*让我们创建树*/
        MenuTree menuTree =new MenuTree(menuList);
        menuList=menuTree.builTree();
        /*转为json看看效果*/
        String jsonOutput= JSON.toJSONString(menuList);
        System.out.println(jsonOutput);
    }
}

下面的这段不用看,临时的
Map(parentId, List) prarentIdTreeNodeMap

private TreeNode buildChilTree(TreeNode pNode){
    List<TreeNode> chilMenus =new  ArrayList<TreeNode>();
	List<treeNode> childrens = prarentIdTreeNodeMap.getKey(pNode.getCatalogId)
	if (childrens != null) {
		for(TreeNode child:childrens){
			buildChilTree(child);
		}
	}
    pNode.setChildren(chilMenus);
    return pNode;
}	

草稿:

source=a,b

source.a.trigger.times=1
source.a.trigger.conditions={index0>1,index1<1}

source.b.trigger.times=2
source.b.trigger.conditions={index0>2,index1<3}

#事件关系
event.level=simple|complex
    #简单事件
    #复杂事件(0:表示事件a,b同时发生)
event.relation=ab

#时间范围 a,b事件的时间范围,注意不支持事件a某个范围,事件b某个范围,事件a,b必须在同一个范围

#事件a和b被认为是同时发生的差异时间
mini.time.a.b=1000

process.operator=


package com.learning.flink;

import org.apache.commons.lang3.StringUtils;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.state.*;
import org.apache.flink.api.common.typeinfo.TypeHint;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.java.functions.KeySelector;
import org.apache.flink.api.java.tuple.Tuple3;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.streaming.api.TimeCharacteristic;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.KeyedStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.KeyedProcessFunction;
import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.util.Collector;

import java.io.Serializable;
import java.util.*;

public class Demo01 {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);

        DataStreamSource<String> source = env.socketTextStream("192.168.66.11", 7777);
        DataStream<Tuple3<String,String,String>> map = source.map(new DemoMapFunction())
                .assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor<Tuple3<String,String,String>>(Time.seconds(3)) {
                    @Override
                    public long extractTimestamp(Tuple3<String,String,String> myTuple) {
                        return Long.parseLong(myTuple.f2);
                    }
                });

        KeyedStream<Tuple3<String,String,String>, String> keyedStream = map.keyBy(new DemoKeySelector());
        keyedStream.process(new DemoKeydProcessFunction()).print();

        env.execute();
    }

}

class DynamicWindow{
    private Long windowStart;
    private Long windowEnd;
   // private List<T> windowData;

    private Map<String,List<SortTuple>> map;

    public Map<String, List<SortTuple>> getMap() {
        return map;
    }

    public void setMap(Map<String, List<SortTuple>> map) {
        this.map = map;
    }
}
class DemoKeydProcessFunction extends KeyedProcessFunction<String, Tuple3<String,String,String>, String> {
    // 3s
    private Long timeRange = 3000L;
    private Long allowDelay = 2000L;
    private Integer  maxCount = 3;
    private ListState<SortTuple> listState;
    private MapState<String,List<SortTuple>> windowDynamic;
    private ValueState<DynamicWindow> dynamicWindow;
    //这个应该直接创建一个名字叫做window的对象好一点
    private ValueState<String> windowRange;
    @Override
    public void open(Configuration parameters) throws Exception {
        listState = getRuntimeContext().getListState(new ListStateDescriptor<SortTuple>("listStatus", TypeInformation.of(new TypeHint<SortTuple>(){} )));
        windowRange = getRuntimeContext().getState(new ValueStateDescriptor<String>("windowRange", String.class));
        windowDynamic= getRuntimeContext().getMapState(new MapStateDescriptor<String, List<SortTuple>>("windowDynamic", TypeInformation.of(String.class), TypeInformation.of(new TypeHint<List<SortTuple>>(){})));
        dynamicWindow = getRuntimeContext().getState(new ValueStateDescriptor<DynamicWindow>("dynamicWindow", DynamicWindow.class));
    }

    public void processElement(Tuple3<String,String,String> myTuple, Context context, Collector<String> collector) throws Exception {
        String windowRangeString = windowRange.value();
        if (StringUtils.isEmpty(windowRangeString)) {
            String windowStart = myTuple.f2;
            String windowEnd = Long.toString((Long.parseLong(myTuple.f2) + timeRange));
            windowRangeString = windowStart+"-"+windowEnd;
            windowRange.update(windowRangeString);
        }
        System.out.println(windowRange.value());

        //如果达到了最大的时间

        //让数据准确的落到窗口内
        String[] split = windowRangeString.split("-");
        Long windowStart = Long.parseLong(split[0]);
        Long windowEnd = Long.parseLong(split[1]);
        if (Long.parseLong(myTuple.f2) >= windowStart && Long.parseLong(myTuple.f2) < windowEnd) {
            //往窗口中落数据
        }

        Map<String, List<SortTuple>> map = dynamicWindow.value().getMap();
        DynamicWindow dynamicWindow = this.dynamicWindow.value();
       
        if (dynamicWindow == null){
            DynamicWindow window = new DynamicWindow();
            Long windowStart1 = Long.parseLong(split[0]);
            Long windowEnd2 = Long.parseLong(split[1]);
            String key = windowStart+"-"+windowEnd;
            Map<String, SortTuple> map1 = new HashMap<String, SortTuple>();
            window.setMap(map);
        }

/*        Iterator<Map.Entry<String, List<SortTuple>>> iterator1 = windowDynamic.iterator();
        if(!iterator1.hasNext()) {
            //iterator1.a
        }
        while (iterator1.hasNext()){
            System.out.println("====");
            Map.Entry<String, List<SortTuple>> next = iterator1.next();
            System.out.println(next.getKey());
        }*/


        Iterator<SortTuple> iterator = listState.get().iterator();
        List<SortTuple> newSortList = new ArrayList();
        Long preListMaxTimeStamp = 0L;

        while (iterator.hasNext()){
            SortTuple tuple = iterator.next();
            //此处其实不需要这么取值的,直接去最后一个元素的最大值就可以了
            preListMaxTimeStamp = Math.max(preListMaxTimeStamp, tuple.getTimeStamp());
            newSortList.add(tuple);
        }
        newSortList.add(new SortTuple(myTuple, Long.parseLong(myTuple.f2), 0));
        Collections.sort(newSortList);
        Long maxTimeStamp = newSortList.get(newSortList.size() -1).getTimeStamp();
        Iterator<SortTuple> newIterator = newSortList.iterator();
        while (newIterator.hasNext()){
            //是否超过时间范围+最大允许的延迟时间
            SortTuple sortTuple = newIterator.next();
            if (sortTuple.getTimeStamp() + timeRange + allowDelay < maxTimeStamp) {
                System.out.println("超过时间没有触发:"+sortTuple);
                newIterator.remove();
            }else {
                sortTuple.setCount(sortTuple.getCount() + 1);

                //如果不是延迟的数据
                if (Long.parseLong(myTuple.f2) > maxTimeStamp) {
                    //不是延迟数据,那么在它之前的数据全部都要+1 (并不是全部+1,需要一个条件的)
                    if (sortTuple.getTimeStamp() +timeRange <maxTimeStamp) { //<=有没有关系,需要分析一下

                    }

                }else {
                    //是延迟数据,那么时间戳在它前面的全部要加1,在它之后的就不变了
                }
                //时间相等的情况也要分析

                if ((sortTuple.getCount() == maxCount) && (sortTuple.getTimeStamp() + timeRange >= maxTimeStamp) ) {
                    System.out.println("已经触发:"+sortTuple);
                    newIterator.remove();
                }else {
                    System.out.println("次数未够,没触发:"+sortTuple);
                }
            }
        }
        listState.update(newSortList);
        collector.collect(myTuple.f0+ "|"+myTuple.f1+"|"+myTuple.f2);
    }
}
class DemoKeySelector implements KeySelector<Tuple3<String,String,String>,String>{

    public String getKey(Tuple3<String,String,String> myTuple) throws Exception {
        return myTuple.getField(0).toString();
    }
}
class DemoMapFunction implements MapFunction<String, Tuple3<String,String,String>> {

    public Tuple3<String,String,String> map(String line) throws Exception {
        String[] arr = line.split("\\|");
        Tuple3<String,String,String> myTuple = new Tuple3<String,String,String>();
        myTuple.setFields(arr[0],arr[1],arr[2]);
        return myTuple;
    }
}
class SortTuple implements Comparable<SortTuple>,Serializable{
    private Tuple3<String,String,String> tuple3;
    private Long timeStamp;
    private int count;

    public SortTuple(Tuple3<String, String, String> tuple3, Long timeStamp, int count) {
        this.tuple3 = tuple3;
        this.timeStamp = timeStamp;
        this.count = count;
    }
    public SortTuple() {
    }

    public Tuple3<String, String, String> getTuple3() {
        return tuple3;
    }

    public void setTuple3(Tuple3<String, String, String> tuple3) {
        this.tuple3 = tuple3;
    }

    public Long getTimeStamp() {
        return timeStamp;
    }

    public void setTimeStamp(Long timeStamp) {
        this.timeStamp = timeStamp;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public int compareTo(SortTuple o) {
        if (this.timeStamp - o.timeStamp > 0) {
            return 1;
        }else if (this.timeStamp - o.timeStamp < 0) {
            return -1;
        }
        return 0;
    }

    @Override
    public String toString() {
        return "SortTuple{" +
                "tuple3=" + tuple3 +
                ", timeStamp=" + timeStamp +
                ", count=" + count +
                '}';
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值