我正在尝试为赋值创建一个图形实现,它包含Graph(GraphImp)对象和Node(NodeImp)对象。
节点对象包含对其图形的引用,x& y坐标和名称。
Graph对象包含其节点的链接列表。
当我尝试将节点添加到节点列表的中间时(附加到最后工作正常),会出现问题。该程序耗尽了堆空间。我不知道为什么会发生这种情况,因为插入到LinkedList的复杂性应该是O(1),而Java(我相信)使用指针,而不是对象本身。我也试过一个arraylist
在这种情况下,使堆更大不是一个选项,并且(据我所知)不应该是问题的根源。
提前致谢。
这是错误:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.LinkedList.addBefore(LinkedList.java:795)
at java.util.LinkedList.add(LinkedList.java:361)
at pt.graph.GraphImp.addNode(GraphImp.java:79)
at pt.graph.NodeImp.<init>(NodeImp.java:25)
at pt.graph.Graphs.newNode(Solution.java:68)
以下是代码:
class Graphs
{
static Node newNode(Graph g, double xpos, double ypos, String name) throws InvalidGraphException,InvalidLabelException
{
if(g==null || !(g instanceof GraphImp)){ //Checking validity of inputs
throw new InvalidGraphException();
}
if(name==null){
throw new InvalidLabelException();
}
NodeImp[] existNodes = ((GraphImp)g).getNodes(); //Get all Nodes already present in the Graph
for(int i=0;i<existNodes.length;i++){
if(existNodes[i].getXPos() == xpos && existNodes[i].getYPos() == ypos){ //If node already present at this position, throw InvalidLabelException()
throw new InvalidLabelException();
}
}
Node n = new NodeImp((GraphImp)g, xpos, ypos, name); //If all inputs are valid, create new node
return n;
}
}
class NodeImp extends Node //Node Class
{
private Object flags = null;
private GraphImp g = null;
private double xpos = 0.0;
private double ypos = 0.0;
private String name = "";
NodeImp(GraphImp g, double xpos, double ypos, String name){
this.g = g;
this.xpos = xpos;
this.ypos = ypos;
this.name = name;
g.addNode(this); // Add Node to the Graph
}
}
class GraphImp extends Graph
{
private LinkedList<NodeImp> nodes = new LinkedList<NodeImp>(); //LinkedList of all Nodes in the Graph
GraphImp(){
}
NodeImp[] getNodes(){ //Returns an array of all Nodes
NodeImp[] nArr = new NodeImp[nodes.size()];
return nodes.toArray(nArr);
}
int countNodes(){ //Returns number of Nodes
return nodes.size();
}
void addNode(NodeImp n){ //Add a Node to the LinkedList in order
boolean added = false;
for(int i = 0;i<nodes.size();i++){
if(n.compareTo(nodes.get(i))<=0 ){
nodes.add(i,n); //fails here
}
}
if(!added){
nodes.add(n);
}
return;
}
}
答案 0 :(得分:3)
问题是在将新节点插入列表中间后,您没有退出循环。您的代码将尝试无限次插入同一节点,因此是OOM。
试试这个:
for(int i = 0;i<nodes.size();i++){
if(n.compareTo(nodes.get(i))<=0 ){
nodes.add(i,n);
added = true;
break;
}
}
顺便说一下,你的插入效率非常低。由于您知道列表已经排序,您可以使用二进制搜索来查找插入点而不是列表的O(n)扫描。您当前的实现是插入n个项目的O(n ^ 2),但它可能是O(n log n)。
答案 1 :(得分:1)
如果没有整个程序,很难诊断OOM
的确切原因,但这里有一个观察结果:
getNodes()
非常低效。您toArray
只需LinkedList
遍历它并查找特定实例。为什么不恰当地使用。contains()
?然后无需复制所有元素。或者只是做你以前做过的事情,但是在List
而不是数组副本上执行:
for(NodeImp n : existingNodes){
if(n.getXPos() == xpos && n.getYPos() == ypos){
throw new InvalidLabelException();
}
}
我的猜测是,添加到最后的'旧'方法也可能会击中OOM,但是由于某些heisenbug原因它没有表现出来。你有使用探查器运行吗?