Java:创建指向同一对象的引用的副本

时间:2014-12-16 13:59:23

标签: java oop

我正在尝试创建图表的邻接列表表示。并且每个顶点在下面定义了四个不同的属性,但我只需要使用node属性进行识别。

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;
    }
}

我使用下面的代码读取文本文件中的数据,并在下面创建一个HashMap<Vertex, ArrayList<Vertex>>对象。下面我的代码的问题是我总是在创建一个新对象,即使已经看过相同的node值,即。我可以创建两个Vertex对象,并且都有node = 5这实际上是非常低效的。此外,当我使用node = 5更改顶点之一并说我将其color属性更改为WHITE时。这不会反映在同样具有node = 5的其他Vertex对象中。

所以,我认为在这种情况下,每当我在文本文件中读取值5两次或更多时,我真正需要的是能够复制对同一对象的引用。但我不知道最好的方法是什么?

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);
        }
    }
   }
}

示例数据文件

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 .

3 个答案:

答案 0 :(得分:1)

一种可能的选择是使用工厂方法而不是构造函数来创建新的Vertex对象,并尽可能重用现有的实例。

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;
    }
    ...
}

答案 1 :(得分:1)

与David的回答类似

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);
        }
    }
}

答案 2 :(得分:0)

您可以设置HashMap<Long, Vertex>,其中node为关键字,vertex对象为值。

Vertex v_l = graph.get(new Long(line[0]));
Vertex v_r = graph.get(new Long(line[1]));

您现在拥有v_lv_r中之前创建的顶点的参考,或者,如果node = line[0]或{{1}的任何顶点的参考}还不存在,你会得到一个line[1],所以你知道你必须首次实例化它们。

这看起来像是作业,所以我不会提供整个方法。