我需要将多个Set<String>
合并为一个Set<String>
。如何在Java中执行此操作?注意,我正在尽可能使用guava
API来帮助解决此问题。例如,我有3个类,如下所示。
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");
}
现在,我需要将这些集合的任意组合合并为一个。例如,我可能需要合并
One.SET
+Two.SET
+Three.SET
为一以产生{“a”,“B”,“c”,“d”,“e”,“f”,“w”,“x”,“y”},One.SET
+Three.SET
合为一以产生{“a”,“B”,“c”,“w”,“x”,“y”,“f”},Two.SET
+Three.SET
合为一以产生{“a”,“d”,“e”,“f”,“w”,“x”,“y”},- 等等
我创建了一个方法来合并一个集合数组Set<String>[]
,但是这个方法不起作用(在这篇SO post Creating an array of Sets in Java中解释)。下面是合并的代码。它可以工作(编译)。
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);
}
下面是调用代码;它不工作(不编译)。
Set<String> set = Utils.immutableSetOf(new Set<String>[] { One.SET, Two.SET });
因此,我修改了我的合并方法,使其对List<Set<String>>
而不是Set<String>[]
进行操作。
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);
}
所以,现在我的调用代码看起来像下面这样。
Set<String> set = Utils.immutableSetOf(
Lists.newArrayList(
One.SET, Two.SET));
这段代码无法编译,因为Lists.newArrayList(...)
返回的是Set<String>
而不是List<Set<String>>
。方法Lists.newArrayList(...)
被重载,当我传入集合时使用的方法签名是List.newArrayList(Iterable<? extends E> elements)
。
那么,问题是,如何定义一个方法来合并任意数量的Set<String>
,同时考虑调用代码?我注意到编译问题是在调用代码上(而不是合并方法),但也许解决方案也与合并代码有关?
更新:我也尝试了varargs,但它产生了自己的警告(Is it possible to solve the "A generic array of T is created for a varargs parameter" compiler warning?)。合并方法签名现在如下所示。
public static Set<String> immutableSetOf(Set<String>... sets)
调用代码现在如下所示,我得到“类型安全:为varargs参数“”创建Set的泛型数组。
Set<String> set = Utils.immutableSetOf(One.SET, Two.SET);
更新:对于接受的答案,我做了以下事情。
@SuppressWarnings("unchecked")
Set<String> set = Utils.immutableSetOf(Set[] { One.SET, Two.SET });
6条答案
按热度按时间4dbbbstv1#
建议使用
com.google.common.collect.Sets#union(set1, set2)
而不是Set.addAll
进行合并,因为Guava已经在您的依赖项中。原因:是view占用内存,而且不可修改。
加:我应该把它作为一个 * 评论 *,对不起。
cbwuti442#
创建一个输入集的集合,然后使用
flatMap
怎么样?z4iuyo4d3#
在你之前的尝试中,你写了
这不起作用,因为,泛型数组创建在Java中是不允许的
试试这个:
之所以这样做是因为,我们创建了一个新的Set[],而没有指定泛型类型,并将其分配给引用Set[] mySet(由于这是一个未检查的操作,因此我们必须向其添加@SuppressWarnings(“unchecked”))
brvekthn4#
您可以用途:
使用您对
immutableSetOf(List<Set<String>> sets)
的定义。没有警告或隐藏的警告。1wnzp6jl5#
我认为
FluentIterable
(在18.0和更高版本中)可以在这里提供帮助,特别是append
方法。有了这些,我们需要定义一个方便的helper方法--是的,我们将为此使用varargs。
如果你不想要一个
TreeSet
,也不想在之后改变你的集合,那么就省略new TreeSet<>
部分,并放松T
的约束。gopyfrb36#
这应该有助于java8中的. onliner-〉Stream.of(sets).flatMap(Set::stream).collect(Collectors.toSet())