0

我试图简单地等于两个 jgraphT 实例,它返回 false,即使它们是相同的。然后我尝试用我的实现覆盖等号:

public boolean equals(MyGraph<CustomV, CustomE> otherGraph){
    boolean result = true;

    Iterator<CustomV> vertexes = otherGraph.vertexSet().iterator();
    while(result && vertexes.hasNext()){
        result = this.containsVertex((V) vertexes.next());  
    }

    Iterator<CustomE> edges = otherGraph.edgeSet().iterator();
    while(result && edges.hasNext())
        result = this.containsEdge((E) edges.next());


    return result;
}

并看到如果该边不是 EXACT 对象,则 containsEdge() 方法将失败。这很奇怪,因为我确保覆盖边缘和开关的 equals 方法......

编辑:做了这个实验:

CustomV aNode = new CustomV(1,2);
myGraph.addVertex(aNode);
System.out.println(myGraph.containsVertex(aNode)); //true
System.out.println(myGraph.containsVertex(new CustomV(1,2))); //false..but should be true

如您所见, containsVertex() 方法似乎不起作用..

edit2:感谢愚蠢的怪胎,我几乎解决了:我也必须覆盖 hashcode() 方法。现在,这适用于顶点,但对于边缘,我在哈希码上得到一个空指针异常,这是我重写的方法:

@Override
public int hashCode() {

    return (getSource().hashCode()+getTarget().hashcode());
}

当我尝试在图上创建一条边时,我得到一个空指针(我想这里调用了 hashcode()):

myGraph.addEdge(a,b);

问题是 getSource() 和 getTarget() 在那一刻调用时似乎返回 null ......如何解决?这是异常堆栈:

java.util.HashMap.hash(HashMap.java:366) 的 org.at.network.types.CustomE.hashCode(CustomE.java:71) 的线程“main”java.lang.NullPointerException 异常。 HashMap.getEntry(HashMap.java:466) at java.util.HashMap.containsKey(HashMap.java:453) at org.jgrapht.graph.Abs​​tractBaseGraph.containsEdge(AbstractBaseGraph.java:359) at org.jgrapht.graph.Abs​​tractBaseGraph org.jgrapht.graph.DefaultListenableGraph.addEdge(DefaultListenableGraph.java:162) 在 org.at.network 的 org.jgrapht.graph.GraphDelegator.addEdge(GraphDelegator.java:131) 的 .addEdge(AbstractBaseGraph.java:208)。 types.MyGraph.addCustomEdge(MyGraph.java:27) 在 org.at.network.Test.main(Test.java:220)

addcustomedge 方法如下:

public CustomE addCustomEdge(V sourceVertex, Port sourcePort, 
        V targetVertex, Port targetPort){
    CustomE l = (CustomE)super.addEdge(sourceVertex, targetVertex);
    l.setSourceP(sourcePort);
    l.setTargetP(targetPort);

    return l;
}

端口只是几个字符串的简单数据结构。

4

1 回答 1

1

For the answer to the intial problem: Overriding equals and hashCode in Java

Whenever a.equals(b), then a.hashCode() must be same as b.hashCode()

that's especially relevant when using hash based data structures, as elements are put in buckets according to their hash codes, and only those in the same bucket are compared using equals().


myGraph.addEdge(a,b); implicitly creates the edge using an EdgeFactory (presumably a ClassBasedEdgeFactory). Look at lines 206 and following in AbstractBaseGraph, where the exception is coming from:

E e = edgeFactory.createEdge(sourceVertex, targetVertex);

if (containsEdge(e)) { // this restriction should stay!

As you said yourself, you use a default constructor to construct the edge (by the way, you don't even seem to set the vertexes at all):

CustomE l = (CustomE)super.addEdge(sourceVertex, targetVertex);
l.setSourceP(sourcePort);
l.setTargetP(targetPort); 

that means, at the time the edge is used by containsEdge, it is not fully initialized! Generally, before exposing an object to code you don't have absolute control over, it should be initialized. You have just experienced one of many problems that can come up when you expose uninitialized objects. In particular, as source and target are still null when containsEdge performs a hash-based lookup, this code:

(getSource() == null? 0:getSource().hashCode())

throws a NullPointerException.

The fix to the problem is to fully initialize the edge before passing it to the JGraphT API. As you not only set source and target vertex but also port, it seems that the EdgeFactory.createEdge() does not have enough information to do so. Luckily, there seems to be an overloaded method Graph.addEdge(V sourceVertex, V targetVertex, E e). I would advise you to use it like this:

public CustomE addCustomEdge(V sourceVertex, Port sourcePort, 
        V targetVertex, Port targetPort){
    CustomE l = new CustomE(sourceVertex, sourcePort, targetVertex, targetPort);
    boolean added = addEdge(sourceVertex, targetVertex, l);
    if(added) return l;
    else return null;
}

of course you first have to create that CustomE constructor.

于 2014-05-27T21:42:50.020 回答