I have the following class that is used as part of a graph :
public class MyNode {
private String name;
private Set<MyNode> parents;
private Set<MyNode> children;
// getters and setters
}
When I use Eclipse's Source / Generate hashCode() and equals()
, it generates this method:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((children == null) ? 0 : children.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((parents == null) ? 0 : parents.hashCode());
return result;
}
The problem is that this method goes from the current object to its children, then while computing the hashCode() of the first child , it gets back to the original node through the parents.hashCode()
but don't know that the hashCode() has already been computed there. It then reenters the children
of the original node, and it gives a beautiful infinite loop.
Question : how can I check that two instances of MyNode
are the same object while, at the same time, avoid the infinite loop? Is this acceptable to add a visited
boolean in the MyNode class, for the purpose of stopping the exploration? Or is there a better solution?
Thanks!
You should not use children or parents of node when implementing hashCode
and equals
. They are mutable properties. Calculation of hashCode
will differ after changing edges and will result in broken Maps and Set collections.
Implement hashCode
and equals
using only immutable fields that makes a distinct natural key for an object. A name might be a good candidate, unless it can be changed.
If no immutable fields exists, either:
hashCode
and equals
methods, defaults will be fine. It will make each class instance unique. hashCode
and comparison in equals
. You can check whether two objects are the same instance using the ==
opearator:
if(obj0 == obj1)
If you want to use a visited
flag you should implement it using a lookup (a Map
for example) since after your code runs you have to reset those flags.
I suggest ignoring parents
/ children
and adding an unique id to each node instead.
The only hard requirement on hashCode()
is that two objects which are equal must return the same hash value.
This implementation would comply:
@Override
public int hashCode() {
return 42;
}
...because nothing says that non-equal objects MUST have different hashcodes.
Of course, to do its job properly, hashCode()
will work better if values can be spread out. You can do anything you like as long as you don't break the rule about equal objects. In normal general-purpose code where I don't expect the hashes to be critical to performance, I generally just return the hashcodes of a significant field or two (eg name in this case), provided that those fields are involved in the computation of equality such that equal objects have the same hash.
The point is, you really need to consider equals
and hashCode
as a pair, and it's better to start with your definition of equals.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.