As the heading suggests, my question has something to do with overriding the hashCode() and equals() method. However, this is also not completely true, I just did not know another way to summarize my question.
I have an object Label
that contains multiple components, one of which is a List
that contains multiple objects of type Node
. An example of Label
would be: [(n1, n2, n3), (n4, n5)]
. I want to store all unique Label
objects generated in a LinkedHashSet
. However, this is not working as expected. Suppose that the LinkedHashSet
currently contains the Label
described above, and that we now generated a new Label
called other
which turned out to contain the same nodes as the already added label, thus also [(n1, n2, n3), (n4, n5)]
. Since it has the same list of nodes, the other components in Label
are also identical. I won't explain here why, just assume that it is, because that is the case. However, when checking if the LinkedHashSet
already contains the Label
it returns false
, since the objects have different object ID's.
One approach would be to write a for-loop over the LinkedHashSet
and compare the new label with all labels in the LinkedHashSet
, but that would be very expensive in terms of running time, so I am looker for a cheaper option. Any suggestion is welcome!
Another approach would be to adapt the equals()
method, but this was not working out, since I also have to adapt the hashCode()
method and I do not know what to change this to to get this working.
You definitely don't want to "for-loop over the LinkedHashSet
and compare..." Detecting duplicates is what the LinkedHashSet
is supposed to do. In order to do that, it needs appropriate implementations of equals
and hashCode
.
You probably understand that you need to implement equals
such that it returns true when a Label
is "equal to" another Label
, however you define that. If two labels are equal when they have the same nodes, then yeah, you pretty much have to look at all the nodes and check that they're the same.
That leaves hashCode
. You must implement hashCode
to be consistent with equals
, that is, if two labels are equal, they must have the same hash code. That's because LinkedHashSet
is going to use the hash code to determine the bucket in which a Label
resides, and then use equals
to compare the new Label
with the ones that already exist in bucket. If two labels are equal but generate different hash codes, LinkedHashSet
won't be able to detect them as duplicates.
The simplest thing to do would be to incorporate the hash codes of all the nodes into the hash code of the Label
. Something like:
int hashCode() {
int hc = 1;
for (Node n : allMyNodes) {
hc = hc * 31 + n.hashCode();
}
return hc;
}
If there are lots of nodes and it's unlikely that two labels will share the same node unless they're "equal," you could just use the hash code of the first node, instead of rummaging through them all.
Implementing equals(...) and hashCode(...) is the right approach here. Usually people use their IDE to generate those methods for them, here is what this would look like with Java 7+:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Label label = (Label) o;
return Objects.equal(nodes, label.nodes);
}
@Override
public int hashCode() {
return Objects.hashCode(nodes);
}
If you have multiple fields this become:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Label label = (Label) o;
return Objects.equal(nodes, label.nodes) &&
Objects.equal(other, label.other);
}
@Override
public int hashCode() {
return Objects.hashCode(nodes, other);
}
However this will only work if the implementations for Node
also implement equals(...)
and hashCode(...)
.
Use @EqualsAndHashCode
from lombok
at your Node
(or Label
) class.
Then you can add nodes to your LinkedHashSet
.
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.