46

What is the simplest way to make a union or an intersection of Sets in Java? I've seen some strange solutions to this simple problem (e.g. manually iterating the two sets).

Union/Intersection of Java sets

Mahozad
  • 18,032
  • 13
  • 118
  • 133
  • 1
    Why do you think that manually iterating the sets is a "strange" solution? – Michael Jun 30 '18 at 08:42
  • 11
    @Michael Because in my opinion when there is a built-in API of java, using that: 1. Reduces my work (lines of code) and improves readability 2. Standardizes the code (other developers understand it with a glimpse) 3. I do not have to maintain it 4. It is automatically updated, improved, optimized,... by java developers – Mahozad Jun 30 '18 at 09:17

5 Answers5

72

The simplest one-line solution is this:

set1.addAll(set2); // Union
set1.retainAll(set2); // Intersection

The above solution is destructive, meaning that contents of the original set1 my change.
If you don't want to touch your existing sets, create a new set:

var result = new HashSet<>(set1);          // In Java 10 and above
Set<Integer> result = new HashSet<>(set1); // In Java < 10
result.addAll(set2); // Union
result.retainAll(set2); // Intersection
Mahozad
  • 18,032
  • 13
  • 118
  • 133
  • instead of using Set result = new HashSet<>(set1); HashSet support clone operation that will far more efficient – Arnault Le Prévost-Corvellec Jun 30 '18 at 08:37
  • 7
    @ArnaultLePrévost-Corvellec reference? Usage of `clone()` is heavily frowned upon and recommended to get avoided in all cases. See [Effective Java 11](https://medium.com/@biratkirat/learning-effective-java-item-11-390fbf94e41c) (Original book, [full PDF](http://wavelino.coffeecup.com/pdf/EffectiveJava.pdf)) (Item 13 in the 3rd edition) – Boris the Spider Jun 30 '18 at 10:41
  • 2
    your are speaking about cloneable interface that could be very tricky to implement and most of the time the contract of clone is not respect by developers. I ll not demonstrate that HashSet.clone() method respect the contract of clone ... please read the code of this methods if you see the difference .here the purpuse is to make a shallow copy that clone made far fastest as the constructor that is code for any collection... hashset add method is quite heavy thats why for perfomance issue clone will be the best way ... – Arnault Le Prévost-Corvellec Jun 30 '18 at 12:47
  • I think if we don't have the constraint about the number of new created sets, this is a good solution – Minh Trần Jun 30 '18 at 17:40
29

While guava for sure is neater and pretty much standard, here's a non destructive way to do union and intersect using only standard Java

Set s1 = Set.of(1,2,3);
Set s2 = Set.of(3,4,5);     

Set union = Stream.concat(s1.stream(),s2.stream()).collect(Collectors.toSet()); 
Set intersect = s1.stream().filter(s2::contains).collect(Collectors.toSet());
Gilad Peleg
  • 2,010
  • 16
  • 29
David Lilljegren
  • 1,799
  • 16
  • 19
  • 1
    Worth noting that with this code, there's no need for `s1` to be a set. Any stream would work without performance degradation (since it's `s2` that's being checked, that's where the set-ness comes into play) – Alexander Jul 19 '19 at 03:04
  • 1
    This is only possible since Java 8 (and Java 9 for `Set.of(...)` set initialization) – fbastien Mar 06 '20 at 18:06
11

You can achieve this using Google's Guava library. The following explanation is given below with the help of an example:

    // Set a
    Set<String> a = new HashSet<String>();
    a.add("x");
    a.add("y");
    a.add("z");

    // Set b
    Set<String> b = new HashSet<String>();
    b.add("x");
    b.add("p");
    b.add("q");

Now, Calculating Intersection of two Set in Java:

Set<String> intersection = Sets.intersection(a, b);
System.out.printf("Intersection of two Set %s and %s in Java is %s %n",
                a.toString(), b.toString(), intersection.toString());

Output: Intersection of two Set [z, y, x] and [q, p, x] in Java is [x]

Similarly, Calculating Union of two Set in Java:

Set<String> union = Sets.union(a, b);
System.out.printf("Union of two Set %s and %s in Java is %s %n",
                a.toString(), b.toString(), union.toString());

Output: Union of two Set [z, y, x] and [q, p, x] in Java is [q, p, x, z, y]

You can read more about guava library at https://google.github.io/guava/releases/18.0/api/docs/

In order to add guava library to your project, You can see https://stackoverflow.com/a/4648947/8258942

Nitin Bisht
  • 5,053
  • 4
  • 14
  • 26
  • 2
    While the library method is nice, I don't see any reason to add a heavyweight library and all the overhead just for set-intersection/union when Java already offers it. Of course, if you already have it in your project you can just use it. – Zabuzard Jun 30 '18 at 10:26
  • 4
    @Zabuza it provides an intersection/union _view_ - which is very different to the JDK options. If you don't need that, of course, then the library is unneccessary. – Boris the Spider Jun 30 '18 at 11:23
  • @Zabuzard The Guava library also offers other set-manipulation methods (difference, complementOf, cartesianProduct, intersection, powerSet, subSet, et al.), so I think it's a great addition to one's toolbox. – Aquarelle Nov 09 '22 at 20:51
1
    import java.util.*;

public class sets {
    public static void swap(int array[], int a, int b) { // Swap function for sorting
        int temp = array[a];
        array[a] = array[b];
        array[b] = temp;
    }

    public static int[] sort(int array[]) { // sort function for binary search (Selection sort)
        int minIndex;
        int j;
        for (int i = 0; i < array.length; i++) {
            minIndex = i;
            for (j = i + 1; j < array.length; j++) {
                if (array[minIndex] > array[j])
                    minIndex = j;
            }
            swap(array, minIndex, i);
        }
        return array;
    }

    public static boolean search(int array[], int search) { // Binary search for intersection and difference
        int l = array.length;
        int mid = 0;
        int lowerLimit = 0, upperLimit = l - 1;
        while (lowerLimit <= upperLimit) {
            mid = (lowerLimit + upperLimit) / 2;
            if (array[mid] == search) {
                return true;
            } else if (array[mid] > search)
                upperLimit = mid - 1;
            else if (array[mid] < search)
                lowerLimit = mid + 1;
        }
        return false;
    }

    public static int[] append(int array[], int add) { // To add elements
        int newArray[] = new int[array.length + 1];
        for (int i = 0; i < array.length; i++) {
            newArray[i] = array[i];
        }
        newArray[array.length] = add;
        newArray = sort(newArray);
        return newArray;
    }

    public static int[] remove(int array[], int index) { // To remove duplicates
        int anotherArray[] = new int[array.length - 1];
        int k = 0;
        if (array == null || index < 0 || index > array.length) {
            return array;
        }
        for (int i = 0; i < array.length; i++) {
            if (index == i) {
                continue;
            }
            anotherArray[k++] = array[i];
        }
        return anotherArray;
    }

    public static void Union(int A[], int B[]) { // Union of a set
        int union[] = new int[A.length + B.length];
        for (int i = 0; i < A.length; i++) {
            union[i] = A[i];
        }
        for (int j = A.length, i = 0; i < B.length || j < union.length; i++, j++) {
            union[j] = B[i];
        }
        for (int i = 0; i < union.length; i++) {
            for (int j = 0; j < union.length; j++) {
                if (union[i] == union[j] && j != i) {
                    union = remove(union, j); // Removing duplicates
                }
            }
        }
        union = sort(union);
        System.out.print("A U B = {"); // Printing
        for (int i = 0; i < union.length; i++) {
            if (i != union.length - 1)
                System.out.print(union[i] + ", ");
            else
                System.out.print(union[i] + "}");
        }
    }

    public static void Intersection(int A[], int B[]) {
        int greater = (A.length > B.length) ? (A.length) : (B.length);
        int intersect[] = new int[1];
        int G[] = (A.length > B.length) ? A : B;
        int L[] = (A.length < B.length) ? A : B;
        for (int i = 0; i < greater; i++) {
            if (search(L, G[i]) == true) { // Common elements
                intersect = append(intersect, G[i]);
            }
        }
        for (int i = 0; i < intersect.length; i++) {
            for (int j = 0; j < intersect.length; j++) {
                if (intersect[i] == intersect[j] && j != i) {
                    intersect = remove(intersect, j); // Removing duplicates
                }
            }
        }
        System.out.print("A ∩ B = {"); // Printing
        for (int i = 1; i < intersect.length; i++) {
            if (i != intersect.length - 1)
                System.out.print(intersect[i] + ", ");
            else
                System.out.print(intersect[i] + "}");
        }
    }

    public static void difference(int A[], int B[]) {
        int diff[] = new int[1];
        int G[] = (A.length > B.length) ? A : B;
        int L[] = (A.length < B.length) ? A : B;
        int greater = G.length;
        for (int i = 0; i < greater; i++) {
            if (search(L, G[i]) == false) {
                diff = append(diff, G[i]); // Elements not in common
            }
        }
        for (int i = 0; i < diff.length; i++) {
            for (int j = 0; j < diff.length; j++) {
                if (diff[i] == diff[j] && j != i) {
                    diff = remove(diff, j); // Removing duplicates
                }
            }
        }
        System.out.println("Where A is the larger set, and B is the smaller set.");
        System.out.print("A - B = {"); // Printing
        for (int i = 1; i < diff.length; i++) {
            if (i != diff.length - 1)
                System.out.print(diff[i] + ", ");
            else
                System.out.print(diff[i] + "}");
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("Enter the operation");
        String operation = sc.next().toLowerCase();
        System.out.println("Enter the length of the first set.");
        int l1 = sc.nextInt();
        System.out.println("Enter the length of the second set.");
        int l2 = sc.nextInt();
        int A[] = new int[l1];
        int B[] = new int[l2];
        System.out.println("Enter the elements of the first set.");
        System.out.print("A = ");
        for (int i = 0; i < l1; i++) {
            A[i] = sc.nextInt();
        }
        System.out.println("Enter the elements of the second set.");
        System.out.print("B = ");
        for (int i = 0; i < l2; i++) {
            B[i] = sc.nextInt();
        }
        A = sort(A); // Sorting the sets before passing
        B = sort(B);
        sc.close();
        switch (operation) {
            case "union":
                Union(A, B);
                break;
            case "intersection":
                Intersection(A, B);
                break;
            case "difference":
                difference(B, A);
                break;
            default:
                System.out.println("Invalid Operation");
        }
    }
}
VamVag
  • 11
  • 2
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community May 15 '22 at 05:34
0

When I think of union and intersection, it is in the first loop an operation on sets, i.e. a map
            Set<T>  x  Set<T>  →  Set<T>
Not clear, why it would appear in Java design that shirtsleeved.

static <T> Set<T> union(Set<T> a, Set<T> b)
{
    Set<T> res = new HashSet<T>(a);
    res.addAll(b);
    return res;
}

static <T> Set<T> intersection(Set<T> a, Set<T> b)
{
    Set<T> res = new HashSet<T>(a);
    res.retainAll(b);
    return res;
}
Sam Ginrich
  • 661
  • 6
  • 7