聊一下我遇到的场景哈,为啥突然要用到这个递归树了呢?
是因为项目中的一个目录树的查询操作,当目录很多的时候,代码中频繁递归查询数据库,和数据库交互次数过多。
后来就想先把所有数据查询出来,构建出树结构,减少和数据库的交互次数
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 +
'}';
}
}