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" },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 });
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...
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With