Course contents

Set operations: union, intersection and difference

Set algebra in Java: union, intersection, difference, symmetric difference, subset checks, disjoint checks, copy-first safety, streams, Guava views, range views and EnumSet bit operations.

PremiumOften askedLesson14 min readCoreReviewed Oct 2026 · Java 21
On this page
  1. Picture it first: Venn diagrams with side effects
  2. The core operations under the hood
  3. Relationship checks: subset, superset and disjoint
  4. Snapshots, streams and Guava views
  5. The removeAll performance trap
  6. Sorted and enum-specific set algebra
  7. Choosing the right form
  8. How to say it in the interview

🔵 What are set operations?

Set operations are the collection version of Venn diagrams: union means everything in either set, intersection means only the overlap, and difference means what remains after removing another set. If one service has product IDs {A, B, C} and another has {B, C, D}, the union is {A, B, C, D}, the intersection is {B, C}, and the first-minus-second difference is {A}.

For this lesson, we'll focus on Java's built-in operations (addAll, retainAll, removeAll, containsAll, Collections.disjoint), how to use them without mutating your inputs, stream alternatives, Guava's view-style utilities, the real AbstractSet.removeAll performance trap, and specialized set algebra with TreeSet ranges and EnumSet bit operations. Interviewers ask this because the code is small, but the mistakes are very common.

Below the line (out of scope)

The 30-second answer

Java set operations are usually mutating methods, so do them on a copy. Union is copy.addAll(other), intersection is copy.retainAll(other), difference is copy.removeAll(other), and symmetric difference is (a - b) union (b - a) or union.removeAll(intersection). containsAll checks subset and superset relationships; Collections.disjoint(a, b) checks whether two collections share no elements. Set.copyOf makes an unmodifiable snapshot, and streams can express the same operations with filter, contains and Collectors.toSet(). The performance catch is that AbstractSet.removeAll picks a branch by collection sizes, not by contains cost, so hashSet.removeAll(largeList) can become O(n*m) when it iterates the set and calls largeList.contains for every element. For sorted data, TreeSet range views act like set algebra over intervals; for enums, EnumSet operations are bit operations.

What you’ll learn

  • Implement union, intersection, difference and symmetric difference with addAll, retainAll and removeAll
  • Avoid accidental mutation by doing set operations on copies and using Set.copyOf for snapshots
  • Check subset, superset and disjoint relationships with containsAll and Collections.disjoint
  • Write stream-based set operations when they improve readability, and preserve order when needed
  • Explain the AbstractSet.removeAll performance trap with large List arguments
  • Use TreeSet range views and EnumSet operations as specialized set algebra

Interview radar

Asked often: How do you get union, intersection and difference of two sets in Java? Senior rounds probe: Which calls mutate, and when can removeAll(list) be much slower than expected? Production angle: A method returns the right answer once, then corrupts a cached set because it called retainAll on the input.

01Picture it first: Venn diagrams with side effects

Think of two sets as two circles. The math is clean, but the Java methods are more like scissors and glue: addAll, retainAll and removeAll modify the receiver. If the receiver is an input parameter, you may have changed your caller's data.

Here is the picture you should keep in your head while writing code.

Fig. 1

Four Venn diagrams show union as both circles, intersection as the overlap, difference as the left-only region, and symmetric difference as both non-overlapping regions

Four Venn diagrams show union as both circles, intersection as the overlap, difference as the left-only region, and symmetric difference as both non-overlapping regions

The default habit is copy first, mutate the copy. That makes the method honest: callers give you sets, you return a new set, and nobody is surprised later.

02The core operations under the hood

Try it yourself first

Before reading on, write the result of each operation for paid = {u1, u2, u3} and active = {u2, u3, u4}.

import java.util.HashSet;
import java.util.Set;

public class SetAlgebra {
    public static void main(String[] args) {
        Set<String> paid = Set.of("u1", "u2", "u3");
        Set<String> active = Set.of("u2", "u3", "u4");

        Set<String> union = new HashSet<>(paid);
        union.addAll(active);

        Set<String> intersection = new HashSet<>(paid);
        intersection.retainAll(active);

        Set<String> difference = new HashSet<>(paid);
        difference.removeAll(active);

        Set<String> symmetricDifference = new HashSet<>(union);
        symmetricDifference.removeAll(intersection);

        System.out.println(union);               // [u1, u2, u3, u4] in some order
        System.out.println(intersection);        // [u2, u3] in some order
        System.out.println(difference);          // [u1]
        System.out.println(symmetricDifference); // [u1, u4] in some order
    }
}

The operations are small because Set already gives us uniqueness. addAll adds every element from the other collection, but duplicates collapse. retainAll keeps only elements that the other collection contains. removeAll removes every element that the other collection contains.

Notice the receiver each time. We mutate union, intersection, difference and symmetricDifference, not paid or active. If you used Set.of, the inputs are unmodifiable anyway, but in production they are often mutable HashSets stored in a cache or object field.

The four operations in one table

Operation Meaning Java pattern Mutates receiver?
Union elements in a or b r = new HashSet<>(a); r.addAll(b); yes
Intersection elements in both r = new HashSet<>(a); r.retainAll(b); yes
Difference elements in a but not b r = new HashSet<>(a); r.removeAll(b); yes
Symmetric difference elements in exactly one set union.removeAll(intersection) yes

For symmetric difference, I prefer the union-minus-intersection version in interviews because it reads like the Venn diagram. If allocation is tight, you can also build a - b, build b - a, then addAll those two sets.

static <E> Set<E> symmetricDifference(Set<E> a, Set<E> b) {
    Set<E> leftOnly = new HashSet<>(a);
    leftOnly.removeAll(b);

    Set<E> rightOnly = new HashSet<>(b);
    rightOnly.removeAll(a);

    leftOnly.addAll(rightOnly);
    return leftOnly;
}

03Relationship checks: subset, superset and disjoint

Some set questions do not ask you to build a new set. They ask about a relationship between two sets.

Premium lesson

Keep reading with the Java Pass

The rest of this lesson is part of Java One-Stop Interview Prep: in-depth explanations, diagrams, model answers and how to say them in the interview.

  • Snapshots, streams and Guava views
  • The removeAll performance trap
  • Sorted and enum-specific set algebra
  • Choosing the right form
  • How to say it in the interview

From ₹199 · one-time payment · No auto-renewal

Practise this topicSets: interview questions & scenarios
Further reading (7)