I have a class Output which basically contains a BitSet with overides on hashCode and equals. Then I have a HashSet of Outputs and I do the following operations :
Set<Output> outputs = new HashSet<>();
Output o1 = new Output();
o1.flip(3);
Output o2 = new Output();
o2.flip(1);
o2.flip(3);
outputs.add(o1);
outputs.add(o2);
If I do a print(outputs) I get
[Output@5a1, Output@5a3]
Now if I do
o2.flip(1);
I get
[Output@5a3, Output@5a3]
which of course, is the normal behavior of a Set, since the Set can't be aware that the hashcode of an element has changed.
If I now do
outputs.remove(o1);
I get
[Output@5a3]
Perfect!
But if I do it again
outputs.remove(o1); //or outputs.remove(o2);
it returns false
and I still have [Output@5a3]
And this is strange since if I do
outputs.contains(o1) -> false
which may explain the remove behavior, altough I don't understand why it returns false since if I do
for(Output o : outputs) {
System.out.println(o.equals(o1));
}
It outputs true
.
Any ideas why this happens?
The complete code:
class Output {
BitSet values;
public Output() {
values = new BitSet(4);
}
public void flip(int index) {
values.flip(index);
}
public int hashCode() {
int hash = 3;
hash = 67 * hash + Objects.hashCode(this.values);
return hash;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Output)) {
return false;
}
Output other = (Output) obj;
return this.values.equals(other.values);
}
}
public class Main {
public static void main(String args[]) {
Set<Output> outputs = new HashSet<>();
Output o1 = new Output();
o1.flip(3);
Output o2 = new Output();
o2.flip(1);
o2.flip(3);
outputs.add(o1);
outputs.add(o2);
System.out.println(outputs);
o2.flip(1);
System.out.println(outputs);
outputs.remove(o1);
System.out.println(outputs);
outputs.remove(o1);
System.out.println(outputs);
for (Output o : outputs) {
System.out.println(o.equals(o1));
}
}
}
Output:
[Output@5a1, Output@5a3]
[Output@5a3, Output@5a3]
[Output@5a3]
[Output@5a3]
true