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);