Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to merge multiple (arbitrary number of) Set<String> into one in Java?

I have multiple Set<String> that I need to merge into one Set<String>. How do I do this operation in Java? Note, I am using using the guava API as best as I can to help out. For example, I have 3 classes as follows.

public class One {
 public static Set<String> SET = Sets.newHashSet("a","b","c");
}
public class Two {
 public static Set<String> SET = Sets.newHashSet("a","d","e","f");
}
public class Three {
 public static Set<String> SET = Sets.newHashSet("w","x","y","f");
}

Now, I need to merge any combination of these sets into one. For, example, I may need to merge

  • One.SET + Two.SET + Three.SET into one to produce { "a","b","c","d","e","f","w","x","y" },
  • One.SET + Three.SET into one to produce { "a","b","c","w","x","y","f" },
  • Two.SET + Three.SET into one to produce { "a","d","e","f","w","x","y" },
  • and so on

I created a method to merge an array of sets, Set<String>[], but that doesn't work (explained here by this SO post Creating an array of Sets in Java). Here's the code to merge. It works (compiles).

public static Set<String> immutableSetOf(Set<String>[] sets) {
 Set<String> set = new HashSet<String>();
 for(Set<String> s : sets) {
  set.addAll(s);
 }
 return ImmutableSet.copyOf(set);
}

Here's the calling code; it doesn't work (doesn't compile).

Set<String> set = Utils.immutableSetOf(new Set<String>[] { One.SET, Two.SET });

So, I modified my merging method to operate on List<Set<String>> instead of Set<String>[]. Only the argument type changed, but I put it here for completeness.

public static Set<String> immutableSetOf(List<Set<String>> sets) {
 Set<String> set = new HashSet<String>();
 for(Set<String> s : sets) {
  set.addAll(s);
 }
 return ImmutableSet.copyOf(set);
}

So, now my calling code looks like the following.

Set<String> set = Utils.immutableSetOf(
 Lists.newArrayList(
  One.SET, Two.SET));

This code does not compile, since Lists.newArrayList(...) is returning Set<String> and not List<Set<String>>. The method Lists.newArrayList(...) is overloaded, and the signature of the method that is used when I pass in sets is, List.newArrayList(Iterable<? extends E> elements).

So, the question is, how do I define a method to merge an arbitrary number of Set<String> while considering the calling code? I note that the compilation problems are on the calling code (not the merging method), but perhaps the solution also relates to the merging code?

Update: I also tried varargs but that produces its own warning (Is it possible to solve the "A generic array of T is created for a varargs parameter" compiler warning?). The merging method signature is now the following.

public static Set<String> immutableSetOf(Set<String>... sets)

The calling code is now the following, and I get "Type safety: A generic array of Set is created for a varargs parameter".

Set<String> set = Utils.immutableSetOf(One.SET, Two.SET);

Update: For the accepted answer, I did the following.

@SuppressWarnings("unchecked")
Set<String> set = Utils.immutableSetOf(Set[] { One.SET, Two.SET });
like image 209
Jane Wayne Avatar asked Dec 03 '14 04:12

Jane Wayne


People also ask

Can you combine sets in Java?

Since a Set does not contain duplicate entries, you can therefore combine the two by: newStringSet. addAll(oldStringSet); It does not matter if you add things twice, the set will only contain the element once...

How can you combine two sets into one?

Press Ctrl+click to highlight two sets, and right-click either set to display a shortcut menu that allows you to Create Combined Set. Drag the pill for the set you want to combine to the left of the other set on the Rows shelf, and select Create Combined Set.


1 Answers

Recommend com.google.common.collect.Sets#union(set1, set2) to get the merge instead of Set.addAll under hood, since Guava is already in your dependencies.

Reason: it's view which is memory effective, and also unmodifiable.

plus: I should have post it as a comment, sorry.

like image 177
卢声远 Shengyuan Lu Avatar answered Nov 14 '22 21:11

卢声远 Shengyuan Lu