java的依赖关系_我应该如何在Java中表示依赖关系图?

package org.madeforall.graph.test;

import java.util.ArrayList;

import java.util.List;

import org.madeforall.graph.Graph;

import org.madeforall.graph.NodeValueListener;

public class TestDependecyGraph {

public static void main(String[] args) {

testWithGenericInt();

testWithGenericString();

}

public static void testWithGenericInt() {

final List nodeValueList = new ArrayList();

Graph graph = new Graph(new NodeValueListener() {

public void evaluating(Integer nodeValue) {

nodeValueList.add(nodeValue);

}

});

graph.addDependency(1, 2);

graph.addDependency(1, 3);

graph.addDependency(3, 4);

graph.addDependency(3, 5);

graph.addDependency(5, 8);

graph.addDependency(2, 7);

graph.addDependency(2, 9);

graph.addDependency(2, 8);

graph.addDependency(9, 10);

graph.generateDependencies();

System.out.println(nodeValueList);

}

public static void testWithGenericString() {

final List nodeValueList = new ArrayList();

Graph graph = new Graph(new NodeValueListener() {

public void evaluating(String nodeValue) {

nodeValueList.add(nodeValue);

}

});

graph.addDependency("a", "b");

graph.addDependency("a", "c");

graph.addDependency("a", "f");

graph.addDependency("c", "d");

graph.addDependency("d", "g");

graph.addDependency("f", "d");

graph.addDependency("h", "e");

graph.generateDependencies();

System.out.println(nodeValueList);

}

}

The first and the second argument of the addDependency method of the Graph class are some two arbitrarily chosen nodes of the oriented graph. Watch out for circular dependencies, because I did not take care of them yet.

Here are the classes.

package org.madeforall.graph;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Set;

/**

*

* Represents a graph of nodes. Every node is of GraphNode type and it has set a

* value of the generic type . It basically derives an evaluation order out

* of its nodes. A node gets the chance to be evaluated when all the incoming

* nodes were previously evaluated. The evaluating method of the

* NodeValueListener is used to notify the outside of the fact that a node just

* got the chance to be evaluated. A value of the node that is of the generic

* type  is passed as argument to the evaluating method.

*

*

* @author nicolae caralicea

*

* @param 

*/

final public class Graph {

/**

* These are basically the nodes of the graph

*/

private HashMap> nodes = new HashMap>();

/**

* The callback interface used to notify of the fact that a node just got

* the evaluation

*/

private NodeValueListener listener;

/**

* It holds a list of the already evaluated nodes

*/

private List> evaluatedNodes = new ArrayList>();

/**

* The main constructor that has one parameter representing the callback

* mechanism used by this class to notify when a node gets the evaluation.

*

* @param listener

*            The callback interface implemented by the user classes

*/

public Graph(NodeValueListener listener) {

this.listener = listener;

}

/**

* Allows adding of new dependicies to the graph. "evalFirstValue" needs to

* be evaluated before "evalAfterValue"

*

* @param evalFirstValue

*            The parameter that needs to be evaluated first

* @param evalAfterValue

*            The parameter that needs to be evaluated after

*/

public void addDependency(T evalFirstValue, T evalAfterValue) {

GraphNode firstNode = null;

GraphNode afterNode = null;

if (nodes.containsKey(evalFirstValue)) {

firstNode = nodes.get(evalFirstValue);

} else {

firstNode = createNode(evalFirstValue);

nodes.put(evalFirstValue, firstNode);

}

if (nodes.containsKey(evalAfterValue)) {

afterNode = nodes.get(evalAfterValue);

} else {

afterNode = createNode(evalAfterValue);

nodes.put(evalAfterValue, afterNode);

}

firstNode.addGoingOutNode(afterNode);

afterNode.addComingInNode(firstNode);

}

/**

* Creates a graph node of the  generic type

*

* @param value

*            The value that is hosted by the node

* @return a generic GraphNode object

*/

private GraphNode createNode(T value) {

GraphNode node = new GraphNode();

node.value = value;

return node;

}

/**

*

* Takes all the nodes and calculates the dependency order for them.

*

*/

public void generateDependencies() {

List> orphanNodes = getOrphanNodes();

List> nextNodesToDisplay = new ArrayList>();

for (GraphNode node : orphanNodes) {

listener.evaluating(node.value);

evaluatedNodes.add(node);

nextNodesToDisplay.addAll(node.getGoingOutNodes());

}

generateDependencies(nextNodesToDisplay);

}

/**

* Generates the dependency order of the nodes passed in as parameter

*

* @param nodes

*            The nodes for which the dependency order order is executed

*/

private void generateDependencies(List> nodes) {

List> nextNodesToDisplay = null;

for (GraphNode node : nodes) {

if (!isAlreadyEvaluated(node)) {

List> comingInNodes = node.getComingInNodes();

if (areAlreadyEvaluated(comingInNodes)) {

listener.evaluating(node.value);

evaluatedNodes.add(node);

List> goingOutNodes = node.getGoingOutNodes();

if (goingOutNodes != null) {

if (nextNodesToDisplay == null)

nextNodesToDisplay = new ArrayList>();

// add these too, so they get a chance to be displayed

// as well

nextNodesToDisplay.addAll(goingOutNodes);

}

} else {

if (nextNodesToDisplay == null)

nextNodesToDisplay = new ArrayList>();

// the checked node should be carried

nextNodesToDisplay.add(node);

}

}

}

if (nextNodesToDisplay != null) {

generateDependencies(nextNodesToDisplay);

}

// here the recursive call ends

}

/**

* Checks to see if the passed in node was aready evaluated A node defined

* as already evaluated means that its incoming nodes were already evaluated

* as well

*

* @param node

*            The Node to be checked

* @return The return value represents the node evaluation status

*/

private boolean isAlreadyEvaluated(GraphNode node) {

return evaluatedNodes.contains(node);

}

/**

* Check to see if all the passed nodes were already evaluated. This could

* be thought as an and logic between every node evaluation status

*

* @param nodes

*            The nodes to be checked

* @return The return value represents the evaluation status for all the

*         nodes

*/

private boolean areAlreadyEvaluated(List> nodes) {

return evaluatedNodes.containsAll(nodes);

}

/**

*

* These nodes represent the starting nodes. They are firstly evaluated.

* They have no incoming nodes. The order they are evaluated does not

* matter.

*

* @return It returns a list of graph nodes

*/

private List> getOrphanNodes() {

List> orphanNodes = null;

Set keys = nodes.keySet();

for (T key : keys) {

GraphNode node = nodes.get(key);

if (node.getComingInNodes() == null) {

if (orphanNodes == null)

orphanNodes = new ArrayList>();

orphanNodes.add(node);

}

}

return orphanNodes;

}

}

package org.madeforall.graph;

import java.util.ArrayList;

import java.util.List;

/**

*

* It represents the node of the graph. It holds a user value that is passed

* back to the user when a node gets the chance to be evaluated.

*

* @author nicolae caralicea

*

* @param 

*/

final class GraphNode {

public T value;

private List> comingInNodes;

private List> goingOutNodes;

/**

* Adds an incoming node to the current node

*

* @param node

*            The incoming node

*/

public void addComingInNode(GraphNode node) {

if (comingInNodes == null)

comingInNodes = new ArrayList>();

comingInNodes.add(node);

}

/**

* Adds an outgoing node from the current node

*

* @param node

*            The outgoing node

*/

public void addGoingOutNode(GraphNode node) {

if (goingOutNodes == null)

goingOutNodes = new ArrayList>();

goingOutNodes.add(node);

}

/**

* Provides all the coming in nodes

*

* @return The coming in nodes

*/

public List> getComingInNodes() {

return comingInNodes;

}

/**

* Provides all the going out nodes

*

* @return The going out nodes

*/

public List> getGoingOutNodes() {

return goingOutNodes;

}

}

package org.madeforall.graph;

/**

* The main mechanism used for notifying the outside of the fact that a node

* just got its evaluation

*

* @author nicolae caralicea

*

* @param 

*/

public interface NodeValueListener {

/**

*

* The callback method used to notify the fact that a node that has assigned

* the nodeValue value just got its evaluation

*

* @param nodeValue

*            The user set value of the node that just got the evaluation

*/

void evaluating(T nodeValue);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值