Reputation: 2268
I have following code:
Set<A> aSet = new HashSet<>();
A a1 = new A(); //{1,"1"}
a1.x = 1;
a1.y = "1";
A a2 = new A(); //{1,"2"}
a2.x = 1;
a2.y = "2";
aSet.add(a1);
aSet.add(a2);
a2.y = "1"; // {1,"2"} ---> {1,"1"}
System.out.println(aSet); //[A{x=1, y="1"}, A{x=1, y="1"}]
//aSet.removeDuplicatesInPlace(); //TODO: is there something like this?
aSet = new HashSet<>(aSet);
System.out.println(aSet); //[A{x=1, y="1"}]
Here, I add 2 different elements of class A
(this class has equals and hashcode methods implemented). Then I change y
property on a2
object to "1". This in effect makes Set has 2 duplicate elements in terms of equals, but set cannot know that, since modifications were done after element was added.
Easiest thing to remove duplicates would be to just make new Set from existing one (as is done in line aSet = new HashSet<>(aSet)
), but I am not sure if there is some set implementation with more efficient implementation of this? Some implementation where I could do just aSet.removeDuplicatesInPlace()
?
Upvotes: 0
Views: 883
Reputation: 9013
It is an error to change an object that is stored in a HashSet (or is a key in a HashMap), in a way that changes the hashCode()
of the Object. Doing so will result in contains(object)
returning false
for both the old and new values of the object. See Are mutable hashmap keys a dangerous practice? for more on this.
I think the best (and most efficient) way to do what you're trying to do is:
aSet.remove(a2);
a2.y = "1";
aSet.add(a2); // will not modify the set if an identical object is already present
Upvotes: 1