DAG:有向无环图
根据定义,可以得到以下两个结论:
@Data
public class TaskDagGraphBO {
private Set nodes = new HashSet<>();
private List edges = new ArrayList<>();
public TaskDagGraphBO() {
}
public TaskDagGraphBO(Long nodesSize) {
this.nodes = new HashSet<>(Integer.parseInt(nodesSize+""));
}
public void addNode(Long node) {
if(!this.nodes.contains(node)){
this.nodes.add(node);
}
}
public void addNodes(List nodes) {
this.nodes.addAll(nodes);
}
public void addEdge(Long from, Long to) {
Optional any = this.edges.stream().filter(e -> e.getFrom().equals(from) && e.getTo().equals(to)).findAny();
if(!any.isPresent()){
TaskDagEdge taskDagEdge = new TaskDagEdge(from, to);
this.edges.add(taskDagEdge);
}
}
public void remove(Long node) {
this.nodes.remove(node);
edges.removeIf(taskDagEdge -> taskDagEdge.getFrom().equals(node) || taskDagEdge.getTo().equals(node));
}
}
public class TaskDagEdge{
Long from;
Long to;
public TaskDagEdge(java.lang.Long start, java.lang.Long end) {
this.from = start;
this.to = end;
}
public Long getFrom() {
return (Long) from;
}
public void setFrom(Long from) {
this.from = from;
}
public Long getTo() {
return (Long) to;
}
public void setTo(Long to) {
this.to = to;
}
}
使用:先添加所有节点,再添加边
taskDagGraphBO.addNode(info.getTaskBasicInfo().getId());
// 根据task依赖生成边
taskDagGraphBO.addEdge(t.getTaskId(), info.getTaskBasicInfo().getId());
@Slf4j
public class TaskDAGUtil {
public static List findPriority1(TaskDagGraphBO graph) {
long start = System.nanoTime();
int size = graph.getNodes().size();
List res = new ArrayList<>();
Queue queue = new LinkedList<>();
Map inDegree = getInDegree(graph);
inDegree.forEach((k,v)->{
if(v.equals(0)){
queue.add(k);
}
});
while (!queue.isEmpty()) {
Long cur = queue.poll();
res.add(cur);
graph.remove(cur);
inDegree = getInDegree(graph);
inDegree.forEach((k,v)->{
if(v.equals(0)){
if(!queue.contains(k)) {
queue.add(k);
}
}
});
}
log.info("taskmigrete.taskdag.sort.time:{}inDegree:{}",System.nanoTime()-start,inDegree);
// 若排序后节点小于 n,说明存在环
return res.size() == size ? res : null;
}
/**
* 始终寻找入度为0的点,直到所有节点加入结果队列
*
* @param graph
* @return
*/
public static List findPriority(TaskDagGraphBO graph) {
List list = new ArrayList<>();
Set nodes = graph.getNodes();
Map inDegree = getInDegree(graph);
int size = nodes.size();
int count = 0;
while (count < size && inDegree.keySet().size() != 0) {
log.info("Finding priority:{}");
for (Map.Entry entry : inDegree.entrySet()) {
log.info("Finding inDegree iterator:{}",entry);
Long key = entry.getKey();
if (entry.getValue() == 0) {
list.add(key);
count++;
graph.remove(key);
inDegree = getInDegree(graph);
}
}
}
return list;
}
/**
* 获取图中节点的入度
*
* @param graph
* @return
*/
public static Map getInDegree(TaskDagGraphBO graph) {
Set nodes = graph.getNodes();
List connectTable = graph.getEdges();
Map map = new ConcurrentHashMap<>();
for (Long node : nodes) {
map.put(node, 0);
}
for (TaskDagEdge taskDagEdge : connectTable) {
map.computeIfPresent(taskDagEdge.getTo(), (k, v) -> v + 1);
}
log.info("Finding inDegree:{}",map);
return map;
}
public static void main(String[] args) {
String s = "{\n" +
"\t\"edges\": [{\n" +
"\t\t\"from\": 1631269768021229570,\n" +
"\t\t\"to\": 1651533478953267521\n" +
"\t}, {\n" +
"\t\t\"from\": 1655549249384906369,\n" +
"\t\t\"to\": 1651533478953267521\n" +
"\t}, {\n" +
"\t\t\"from\": 1656941044568217217,\n" +
"\t\t\"to\": 1656941044568184449\n" +
"\t}, {\n" +
"\t\t\"from\": 1656941044568209025,\n" +
"\t\t\"to\": 1656941044568184449\n" +
"\t}, {\n" +
"\t\t\"from\": 1656941044568331905,\n" +
"\t\t\"to\": 1656941044568184449\n" +
"\t}, {\n" +
"\t\t\"from\": 1656941044568217217,\n" +
"\t\t\"to\": 1656941044568200833\n" +
"\t}, {\n" +
"\t\t\"from\": 1656941044568217217,\n" +
"\t\t\"to\": 1656941044568209025\n" +
"\t}, {\n" +
"\t\t\"from\": 1656941044568200833,\n" +
"\t\t\"to\": 1656941044568209025\n" +
"\t}, {\n" +
"\t\t\"from\": 1656941044568200833,\n" +
"\t\t\"to\": 1656941044568331905\n" +
"\t}],\n" +
"\t\"nodes\": [1656941044568331905, 1628668617357041665, 1628655409208832002, 1656941044568184449, 1656941044568192641, 1656941044568200833, 1656941044568209025, 1656941044568217217, 1631269768021229570, 1655772785192377409, 1631476828683976706, 1651533478953267521, 1627858007982931970, 1655549249384906369]\n" +
"}";
String ege = "[{\n" +
"\t\t\"from\": 1631269768021229570,\n" +
"\t\t\"to\": 1651533478953267521\n" +
"\t}, {\n" +
"\t\t\"from\": 1655549249384906369,\n" +
"\t\t\"to\": 1651533478953267521\n" +
"\t}, {\n" +
"\t\t\"from\": 1656941044568217217,\n" +
"\t\t\"to\": 1656941044568184449\n" +
"\t}, {\n" +
"\t\t\"from\": 1656941044568209025,\n" +
"\t\t\"to\": 1656941044568184449\n" +
"\t}, {\n" +
"\t\t\"from\": 1656941044568331905,\n" +
"\t\t\"to\": 1656941044568184449\n" +
"\t}, {\n" +
"\t\t\"from\": 1656941044568217217,\n" +
"\t\t\"to\": 1656941044568200833\n" +
"\t}, {\n" +
"\t\t\"from\": 1656941044568217217,\n" +
"\t\t\"to\": 1656941044568209025\n" +
"\t}, {\n" +
"\t\t\"from\": 1656941044568200833,\n" +
"\t\t\"to\": 1656941044568209025\n" +
"\t}, {\n" +
"\t\t\"from\": 1656941044568200833,\n" +
"\t\t\"to\": 1656941044568331905\n" +
"\t}]";
JSONArray objects = JSONArray.parseArray(ege);
List taskDagEdges = new ArrayList<>(objects.size());
for(int i=0;i(){});
taskDagGraphBO.setEdges(taskDagEdges);
List priority1 = TaskDAGUtil.findPriority1(taskDagGraphBO);
System.out.println(priority1);
}
}