我试图简单地等于两个jgraphT实例并返回false,即使它们是相同的。 然后我尝试用我的实现覆盖equals:
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()方法将失败。这很奇怪,因为我确保覆盖边缘和开关的等于方法......
编辑: 做了这个实验:
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()方法。 现在,这适用于Vertexes但是对于边缘我在哈希码上得到一个空指针异常,这是我的重写方法:
@Override
public int hashCode() {
return (getSource().hashCode()+getTarget().hashcode());
}
当我尝试在图形上创建边时,我得到一个空指针(我想这里调用了hashcode()):
myGraph.addEdge(a,b);
问题是getSource()和getTarget()似乎在那一刻被调用时返回null ...如何解决? 这是异常堆栈:
线程“main”java.lang.NullPointerException中的异常 在org.at.network.types.CustomE.hashCode(CustomE.java:71) 在java.util.HashMap.hash(HashMap.java:366) 在java.util.HashMap.getEntry(HashMap.java:466) 在java.util.HashMap.containsKey(HashMap.java:453) at org.jgrapht.graph.AbstractBaseGraph.containsEdge(AbstractBaseGraph.java:359) 在org.jgrapht.graph.AbstractBaseGraph.addEdge(AbstractBaseGraph.java:208) 在org.jgrapht.graph.GraphDelegator.addEdge(GraphDelegator.java:131) 在org.jgrapht.graph.DefaultListenableGraph.addEdge(DefaultListenableGraph.java:162) 在org.at.network.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;
}
端口只是几个字符串的简单数据结构。
答案 0 :(得分:1)
对于初始问题的答案:Overriding equals and hashCode in Java
每当a.equals(b),则a.hashCode()必须与b.hashCode()相同
在使用基于散列的数据结构时特别相关,因为元素根据其哈希码放入存储桶中,并且只使用equals()
对同一存储桶中的元素进行比较。
myGraph.addEdge(a,b);
使用EdgeFactory
隐含地创建边缘(可能是ClassBasedEdgeFactory
)。查看AbstractBaseGraph
中的第206行和后续行,其中异常来自:
E e = edgeFactory.createEdge(sourceVertex, targetVertex);
if (containsEdge(e)) { // this restriction should stay!
正如你自己所说,你使用默认构造函数来构造边缘(顺便说一下,你甚至似乎都没有设置顶点):
CustomE l = (CustomE)super.addEdge(sourceVertex, targetVertex);
l.setSourceP(sourcePort);
l.setTargetP(targetPort);
这意味着,在containsEdge
使用边缘时,它未完全初始化!通常,在将对象暴露给代码之前,您没有绝对控制权,它应该被初始化。您刚刚遇到了暴露未初始化对象时可能出现的许多问题之一。特别是,当null
执行基于散列的查找时,源和目标仍为containsEdge
,此代码为:
(getSource() == null? 0:getSource().hashCode())
抛出NullPointerException
。
问题的解决方法是在将边缘传递给JGraphT API之前完全初始化边缘。由于您不仅设置了源和目标顶点,还设置了端口,EdgeFactory.createEdge()
似乎没有足够的信息来执行此操作。幸运的是,似乎有一个重载方法Graph.addEdge(V sourceVertex, V targetVertex, E e)
。我建议你这样使用它:
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;
}
当然,您首先必须创建CustomE
构造函数。