What is the best way get the symmetric difference between two sets in java?
You want the symmetric difference.
public static <T> Set<T> diff(final Set<? extends T> s1, final Set<? extends T> s2) {
Set<T> symmetricDiff = new HashSet<T>(s1);
symmetricDiff.addAll(s2);
Set<T> tmp = new HashSet<T>(s1);
tmp.retainAll(s2);
symmetricDiff.removeAll(tmp);
return symmetricDiff;
}
If you want a library, Apache Commons CollectionUtils has
CollectionUtils.disjunction(s1, s2)
which returns a non-generic Collection
.
and Guava Sets has
Sets.symmetricDifference(s1, s2)
which returns an unmodifiable Set
as a generic Sets.SetView
.
Guava is a bit more modern, supporting generics, but either of these will work.
You can use some functions from the Google Guava library (which is really great, I strongly recommend it!):
Sets.difference(s1, s2);
Sets.symmetricDifference(s1, s2);
Javadocs for difference() and symmetricDifference()
symmetricDifference()
does exactly what you are asking for, but difference()
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
):
Set<String> intersection = new HashSet<String>(set1);
intersection.retainAll(set2);
Set<String> difference = new HashSet<String>();
difference.addAll(set1);
difference.addAll(set2);
difference.removeAll(intersection);