Search code examples
javaneo4jjung

Redundant duplicate nodes being created in JUNG graph


I'm having an issue with rendering a Jung graph - the graph is creating duplicate nodes for some reason.

I load the nodes (two different types into a custom Vertex class (MovieVertex extends RootNode implements NodeInfo and PersonVertex extends RootNode implements NodeInfo) - RootNode has a name field that I display on the vertex label using the following code:

      DirectedSparseGraph<NodeInfo,String> g = new DirectedSparseGraph<NodeInfo, String>();
// Code to read node data from a Neo4j graph database
      List<Map<String, Object>> nodes = grapher.read(cql);

      try (Session session = grapher.driver.session()){
             StatementResult result = session.run(cql2);
                while (result.hasNext()) {
                  Record record = result.next();
                  String targetNode = record.get(1).get("title").toString();
                  String sourceNode = record.get(0).get("name").toString();
                  String tagline = record.get(1).get("tagline").toString();
                  String released = record.get(1).get("released").toString();
                  int born = record.get(0).get("born").asInt();
                  String rel = sourceNode + "-ACTED_IN-"+ targetNode;
                  //The problem is probably here - it is creating duplicate vertices for the same data
                 MovieVertex mv = new MovieVertex(targetNode,tagline,released);
                 PersonVertex pv = new PersonVertex(sourceNode,born);
                  g.addVertex(pv);

                  g.addVertex(mv);
                  g.addEdge(rel, pv, mv);
                  ISOMLayout<NodeInfo,String> layout = new ISOMLayout<NodeInfo,String>(g);

                VisualizationViewer<NodeInfo,String> vv =
          new VisualizationViewer<NodeInfo,String>(layout, new Dimension(800,800));

                vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
               JFrame frame = new JFrame();
               frame.getContentPane().add(vv);
               frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
               frame.pack();
               frame.setVisible(true);
            } 

enter image description here Edit: I added the following code to the Vertex custom classes to address the problem, updated graph example:

    @Override
    public boolean equals(Object o) {

        if (o == this) return true;
        if (!(o instanceof MovieVertex)) {
            return false;
        }

        MovieVertex mv = (MovieVertex) o;

        return new EqualsBuilder()
                .append(title, mv.title)
                .append(tagline, mv.tagline)
                .append(released, mv.released)
                .isEquals();
    }

  @Override
    public int hashCode() {
        return new HashCodeBuilder(17, 37)
                .append(title)
                .append(tagline)
                .append(released)
                .toHashCode();
    }

enter image description here


Solution

  • This is a common problem with any custom Java class that is used as a Map key (as JUNG Vertices are). Unless you override the equals and hashCode method in your custom Vertex class, you will get duplicates. You would see the same problem if you added your MovieVertex or PersonVertex instances to a java.util.Set or used them as keys in a Map. Perhaps you can use your name field to compute the value for hashCode and to determine when the Vertices are equal.