2014-12-16 2 views
1

Я пытаюсь создать представление списка смежности графа. И каждая вершина определена ниже с четырьмя различными атрибутами, но мне нужно использовать атрибут node для целей идентификации.Java: Создание копии ссылки, указывающей на тот же объект

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. Это не будет отражено в другом объекте Vertex, который также имеет node = 5.

Итак, я думаю, что в этой ситуации мне действительно нужно иметь возможность сделать копию ссылки на тот же объект, всякий раз, когда я дважды читаю значение 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 . 
+0

Я не уверен, что понял, что вы пытаетесь спросить. Почему бы не создать Vertex node5Ref, а затем указать другие вершины с узлом = 5. Затем вы можете изменить атрибут node5Ref, и они будут отражены в других копиях. –

+0

Да, это то, что я хочу сделать. Но как бы вы это сделали в моем коде? И мой текстовый файл имеет миллионы строк. Обратите внимание, что я читаю только одну строку за раз из текстового файла. – mynameisJEFF

+0

Все вершины с узлом = 5 всегда имеют одинаковые атрибуты (цвет, d и pi?) –

ответ

1

Одним из возможных вариантов является использование фабричный метод вместо конструктора для создания новых объектов вершинных и повторно использовать существующие экземпляры всякий раз, когда это возможно.

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

Подобный ответ Давида

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

Да, это вроде как решение, с которым я столкнулся, - это, по существу, создать еще один hashmap . Я все еще пытаюсь понять, что делает метод Дэвида. Я запутался в ключевом слове 'sychronized', которого я раньше не видел. – mynameisJEFF

+0

'sychronized' - это предотвращение проблем параллелизма, чтобы предотвратить, чтобы разные потоки выполнения пытались вызвать« одновременно »метод. В вашем сценарии у вас нет этой проблемы, но если вы программируете свой метод как часть общедоступного интерфейса класса (как это сделал Дэвид), который может когда-нибудь использоваться в разных сценариях (многопоточность), то это хорошая практика для предотвратите это. – leonbloy

+0

Метод заключается в создании объектов вместо использования конструктора. Пример: Vertex.getInstance (5); вместо новой вершины (5); таким образом, класс управляет созданными экземплярами, и вы можете вернуть уже созданные объекты. Как сказал @leonbloy, синхронизация предназначена для целей параллелизма, поэтому, вероятно, это не относится к вашей заявке –

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_l и v_r, или, если какие-либо из вершин с node = line[0] или line[1] еще не существует, вы получите null, так что вы будете знайте, что вы должны создавать их в первый раз.

Это выглядит как домашнее задание, поэтому я не буду предлагать весь метод.

Смежные вопросы