I'm wondering if there is a quick/clean way to get the symmetric difference between two sets ?
I have:
Set<String> s1 = new HashSet<String>();
s1.add("a");
s1.add("b");
s1.add("c");
Set<String> s2 = new HashSet<String>();
s2.add("b");
I need something like:
Set<String> diff = Something.diff(s1, s2);
// diff would contain ["a", "c"]
Just to clarify I need the symmetric difference.
Loop through one set and compare.
It's only
O(n)
to loop through one of the sets. Consider this code:And the
newSet
will now contain only the unique entries from both sets. It's fast, because you only need to loop through the elements in one of the sets and you don't have to create sets unless you explicitly need a copy.}
Java 8 Solution
We can write two utility methods (for java 8 and prior) in some class
SetUtils (say)
as:The method
add
returns false if element already exists and method negate is used to negate the predicate.Java 11
We have a Predicate#not method for predicate in Java 11 and can use it as:
Should work.
You can use some functions from the Google Guava library (which is really great, I strongly recommend it!):
Javadocs for difference() and symmetricDifference()
symmetricDifference()
does exactly what you are asking for, butdifference()
is also often helpful.Both methods return a live view, but you can for example call
.immutableCopy()
on the resulting set to get a non-changing set. If you don't want a view, but need a set instance you can modify, call.copyInto(s3)
. See SetView for these methods.If you can use Apache-Commons Collections, you are looking for
CollectionUtils.disjunction(Collection a, Collection b)
. It returns the symmetric difference of both Collections.If not, substract (
removeAll
) the intersection (retainAll
) of both sets to the union of both (addAll
):