This is not easy and requires knowing beforehand an explicit list of types you support. This gets complicated even further by the fact that the immutable types returned by e.g. java.util.List.of(a, b)
aren't public types, and their fully qualified type name is not part of the spec (meaning: It could change in a next release of java and that would not be considered a backwards compatibility break; therefore if you rely on the name, your code has a high maintenance burden).
A better idea is perhaps to allow any type of collections, and even a heterogenous list of collections (toss a set, a guava ImmutableList, and a List.of() at it, and a Collections.singleton - your code doesn't care and will merge them all), and have various methods that each return a specifically desired kind of collection.
For example:
import com.google.common.collect.ImmutableList;
public static <K> ImmutableList<K> mergeToList(Collection<K>... collections) {
var out = ImmutableList.<K>builder();
for (Collection<K> c : collections) out.addAll(c);
return out.build();
}
The alternative would be something quite ugly, such as:
import com.google.common.collect.ImmutableList;
public static <K, C extends Collection<K>> C merge(C... collections) {
if (collections.length == 0) throw new IllegalArgumentException("So many problems; one of them is that it becomes impossible to merge zero collections");
Class<?> type = collections[0].getClass();
for (C c : collections) if (c.getClass() != type) throw new IllegalArgumentException("Only pass one kind of collection");
if (type == ImmutableList.class) {
// specific code to merge immutable lists.
} else if (type == Collections.singleton("dummy").getClass()) {
// specific code to merge j.u.Collections singletons.
} else if (type == List.of().getClass()) {
// this becomes virtually impossible; List.of()'s returned type depends on the number of args...
} else {
throw new IllegalArgumentException("Unsupported type: " + type);
}
}
Hopefully that makes clear why you really can't do this. A final option is to have a merge method that takes as parameter a type to merge into, but there is no way to know how to MAKE a collection type. Given com.google.common.collect.ImmutableList
, without hardcoding into your source code how to do it, how would you know how to construct a new one?
This is why factories exist in java, and you need one here. collections don't ship with them, so you'd have to explicitly write them for each type you want to support.