Reputation: 633
lang.StackOverflow exception in my code, but I think the issue is with IntelliJ rather than the code issue. So here is the deal (pieces of code):
case class Node(data: Int, children: ListBuffer[Node], parents: ListBuffer[Node])
val node1 = Node(thisGuy, ListBuffer[Node](), ListBuffer[Node]())
val node2 = Node(thatGuy, ListBuffer[Node](), ListBuffer[Node](node1))
node1.children.append(node2)
var nodes: mutable.Set[Node] = mutable.Set(node1)
// This is were I am getting stackoverflow exception
nodes.add(node2)
What am I missing here?
EDIT : I suspect this has something to do with toString method. But I am not calling toString method on Node class. Any chance that intellij is calling that method? If so, how to suppress it.
TIA
Upvotes: 0
Views: 204
Reputation: 2220
When you add node2
as a child of node1
it creates a circular dependency.
If you check what scala compiler generated for it:
scalac -Xprint:typer NodeTest.scala
the hashCode function is like this:
override <synthetic> def hashCode(): Int = {
<synthetic> var acc: Int = -889275714;
acc = Statics.this.mix(acc, data);
acc = Statics.this.mix(acc, Statics.this.anyHash(children));
acc = Statics.this.mix(acc, Statics.this.anyHash(parents));
Statics.this.finalizeHash(acc, 3)
};
So for node1 to calculate hash code: it needs hash code of node2 (since node2 is a child of node1) and two calculate hash code of node2 it needs hash code of node1 (since node1 is parent of node2)
Why hash code is important here?
Because you are using Set which check if an element already exist before putting it in using hash code.
BTW have you noticed that:
node1.children.append(node2)
node1
Also gives stackoverflow. I am not sure why but looks like toString also has issues with circular dependency.
EDIT: Case classes are generally meant for immutable data structures. So to model what you are trying to achieve you can use class.
class Node(val data: Int) {
var parents : ListBuffer[Node] = ListBuffer[Node]()
var children : ListBuffer[Node] = ListBuffer[Node]()
}
scala> val node1 = new Node(1)
node1: Node = Node@624ea235
scala> val node2 = new Node(2)
node2: Node = Node@12591ac8
scala> node1.children.append(node2)
scala> node2.parents.append(node1)
Upvotes: 2
Reputation: 10671
I suppose you have infinite recursion in equals
or hashCode
methods because of your class hierarchy. Instances of Node
have cyclic references to their parents and children so one of these methods runs infinitely.
Upvotes: 1