I have a Location POJO that stores Location objects parsed in from a JSON file, which I want to map to a graph. Each node's location in the graph corresponds to it's id field, where id="1" is the start node and id="10" is the goal node.
To solve this I adapted a Node class to include methods such as setWeight()
, addChildLocation()
etc , But I'm not sure how to create the graph from my list of locations. I know how to create the graph by hard coding the location's and calling addChildren, by doing the following, but not sure how to create it from a list of already available Location objects:
Node LocationOne= new Node("LocationOne", 170);
LocationOne.addChildNode(LocationTwo, 105);
My thoughts on this problem, are that a for..each
loop should be used to loop through the locations in the list, and add each location as a child of the previous.
Basically, I'm wondering how the list of Location object's can be iterated through, and addChild be called on each sequential location?
Below is the Location class I'm using to map the Location's to object representations:
public class Location {
private Location[] location;
private int id;
private String description;
private String weight;
private String name;
private Exit[] exit;
private boolean visited = false;
private boolean goalLocation;
private int approximateDistanceFromGoal = 0;
private Location parent;
private Map<Location, Integer> children = new HashMap<Location, Integer>();
public Location() {
super();
}
public Location(String name){
this.name = name;
}
public Location(String name, int goalDistance){
this.name = name;
this.approximateDistanceFromGoal = goalDistance;
}
public Location[] children(){
return (Location[]) children.keySet().toArray(new Location[children.size()]);
}
public int getDistance(Location loc){
if(children.get(loc) == null) System.out.println(this.name + ": " + loc.getName());
return children.get(loc);
}
public int getChildLocationCount(){
return children.size();
}
public void addChildLocation(Location child, int distance){
children.put(child, distance);
}
public boolean isLeaf(){
if (children.size() > 0){
return false;
}else{
return true;
}
}
public void removeChild(Location child){
children.remove(child);
}
public Location[] getLocation() {
return location;
}
public void setLocation(Location[] location) {
this.location = location;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDescription ()
{
return description;
}
public void setDescription (String description)
{
this.description = description;
}
public String getWeight() {
return weight;
}
public void setWeight(String weight) {
this.weight = weight;
}
public String getName ()
{
return name;
}
public void setName (String name)
{
this.name = name;
}
public Exit[] getExit() {
return exit;
}
public void setExit(Exit[] exit) {
this.exit = exit;
}
public boolean isVisited() {
return visited;
}
public void setVisited(boolean visited) {
this.visited = visited;
}
public boolean isGoalLocation() {
return goalLocation;
}
public void setGoalLocation(boolean goalLocation) {
this.goalLocation = goalLocation;
}
public int getApproximateDistanceFromGoal() {
return approximateDistanceFromGoal;
}
public void setApproximateDistanceFromGoal(int approximateDistanceFromGoal) {
this.approximateDistanceFromGoal = approximateDistanceFromGoal;
}
public Location getParent() {
return parent;
}
public void setParent(Location parent) {
this.parent = parent;
}
@Override
public String toString() {
return "Location [location=" + Arrays.toString(location) + ", id=" + id
+ ", description=" + description + ", weight=" + weight
+ ", name=" + name + ", exit=" + Arrays.toString(exit)
+"]";
}
}
I am not sure that I completely understand but do the names in the 'Exits' array become children nodes? Not sure what methods are on the Exit object or if this is even remotely the most efficient solution plus I can't check the syntax at the moment unfortunately.
The idea is that the method takes a node, finds the child node and then invokes the method on that node effectively recursively 'walking' down the hierarchy.
If you want to build a graph of any kind, then recognize That a graph is composed of on 2 basic elements:
Key properties:
Practically speaking, how you access these will depend on a trade off between functionality and performance. In addition, graph nodes are worthless if they don't contain some of your information. So, we add
So we can store some data like:
We also use named edges so you can do things like:
I have put together the basic structure for how I would implement a generic graph. But some have pointed out that there are graph DB's out there like Neo which are very sophisticated.
Below is the code. Use it if you'd like to model your locations.
You might consider moving this question to codereview.stackexchange.com
Imagine you code like this:
Your code will be difficult to work with because you don't have declared edges. One of the properties of an edge is "weight" but here you have it as location's property.
As for implementing "visited" -- this is a call-state not a graph wide state. But, by making it part of the Location you now have a state management problem; Imagine trying to "find" something again? You would have to reset the 'visited' property on every node or throw away and create the whole graph again. Very inefficient and error prone.
if you implement DFS, which is really easy recursively or even with a tail loop, you pass the "visited" state along with the dfs method call. Example:
Note that this next method is private.
This is a rough outline. If you reach out to me in Java chat I will give more input and eventually something more slick and reusable. I make no claim the above DFS works. But it's close