Reputation: 4239
I am trying to create an adjacency list representation of a graph. And each vertex is defined below with four different attributes but I only need to use the node
attribute for identification purpose.
class Vertex{
private long node;
private String color;
private long d;
private long pi;
public Vertex(long node){
this.node = node;
}
// to String
public String toString(){
return node+"";
}
public int hashCode(){
return (int)(node * 31);
}
public boolean equals(Object o) {
if (o == this){
return true;
}
if (o == null || getClass() != o.getClass()){
return false;
}
Vertex other = (Vertex)o;
return node == other.node;
}
}
I use the code below to read in the data in a text file and create a HashMap<Vertex, ArrayList<Vertex>>
object below. The problem with my code below is that I am always creating a new object, even the the same node
value has been seen once already,i.e. I could be creating two Vertex objects and both have node = 5
This is actually quite inefficient. Moreover, when I make changes to the one of Vertex with node = 5
and say I change its color
attribute to WHITE
. This will not be reflected in the other Vertex object that also has node = 5
.
So, I think in this situation, what I really need is to be able to make a copy of the reference to the same object, whenever I read the value 5
twice or more in the text file. But I do not know what is the best way to do this ?
class other_class{
public HashMap<Vertex, ArrayList<Vertex>> read_file(String file_loc) throws IOException {
HashMap<Vertex, ArrayList<Vertex>> graph = new HashMap<Vertex, ArrayList<Vertex>>();
FileInputStream fil = new FileInputStream(file_loc);
BufferedReader br = new BufferedReader( new InputStreamReader(fil));
String element = null;
while( (element = br.readLine()) != null){
String[] line = element.split("\\s");
Vertex v_l = new Vertex( Long.parseLong(line[0]) );
Vertex v_r = new Vertex( Long.parseLong(line[1]) );
if(graph.containsKey(v_l) == false){
ArrayList<Vertex> edges_of_this_vertex = new ArrayList<Vertex>();
edges_of_this_vertex.add(v_r);
graph.put(v_l, edges_of_this_vertex);
} else{
graph.get(v_l).add(v_r);
}
}
}
}
Example data file
1 5
1 2
5 1 <-- The 5 here creates a new Vertex object, which is not ideal, I want to be a copy of the reference to the Vertex object on line 1 with node equal to 5 .
Upvotes: 1
Views: 107
Reputation: 537
You could make a HashMap<Long, Vertex>
in which you will use the node
as key, and the vertex
object as value.
Vertex v_l = graph.get(new Long(line[0]));
Vertex v_r = graph.get(new Long(line[1]));
You now have the references for the previously created vertices in v_l
and v_r
, or, if any of the vertices with node
= line[0]
or line[1]
doesn't exist yet, you will get a null
, so you will know you have to instantiate them for the first time.
This looks like homework so I will not provide the whole method.
Upvotes: 0
Reputation: 75896
Similar to David's answer
private static Vertex getVertex(Map<Long,Vertex> vs,long id) {
if(! vs.containsKey(id)) vs.put(id,new Vertex(id));
return vs.get(id);
}
public static void loadGraph() throws Exception {
HashMap<Vertex, ArrayList<Vertex>> graph = new HashMap<Vertex, ArrayList<Vertex>>();
FileInputStream fil = new FileInputStream("C:/temp/x.txt");
BufferedReader br = new BufferedReader( new InputStreamReader(fil));
String element = null;
Map<Long,Vertex> verts = new HashMap<Long,Vertex>();
while( (element = br.readLine()) != null){
String[] line = element.split("\\s+");
Vertex v_l = getVertex(verts, Long.parseLong(line[0]) );
Vertex v_r = getVertex(verts, Long.parseLong(line[1]) );
if(graph.containsKey(v_l) == false){
ArrayList<Vertex> edges_of_this_vertex = new ArrayList<Vertex>();
edges_of_this_vertex.add(v_r);
graph.put(v_l, edges_of_this_vertex);
} else{
graph.get(v_l).add(v_r);
}
}
}
Upvotes: 1
Reputation: 3519
One possible option is to use a factory method instead of a constructor to create new Vertex objects and reuse the existing instances whenever possible.
class Vertex{
...
private static Map<Long, Vertex> instances = new HashMap<Long, Vertex>();
public static synchronized Vertex getInstance(long node) {
if (instances.containsKey(node)) {
return instances.get(node);
} else {
Vertex vertex = new Vertex(node);
instances.put(node, vertex);
return vertex;
}
}
private Vertex(long node){
this.node = node;
}
...
}
Upvotes: 1