我需要将多个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帖子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 });
答案 0 :(得分:6)
建议com.google.common.collect.Sets#union(set1, set2)
获取合并而不是Set.addAll
,因为Guava已经在您的依赖项中。
原因:它的视图是内存有效的,也是不可修改的。
加:我应该将其发布为评论,抱歉。
答案 1 :(得分:1)
在您之前的尝试中,您已写过
Set<String> set = Utils.immutableSetOf(new Set<String>[] { One.SET, Two.SET });
这不起作用,因为在java中不允许创建泛型数组
试试这个:
@SuppressWarnings("unchecked")
Set<String>[] mySet = new Set[] { One.SET, Two.SET };
Set<String> set = Utils.immutableSetOf(mySet);
这个工作原因是因为我们创建了一个新的Set []而没有指定泛型类型并将其分配给引用Set [] mySet(因为这是一个未经检查的操作,我们必须添加@SuppressWarnings(&#34) ;未选中&#34;)到它)
答案 2 :(得分:1)
您可以使用:
Set<String> set = immutableSetOf(Arrays.asList(One.SET, Two.SET));
使用您对immutableSetOf(List<Set<String>> sets)
的定义。没有警告或抑制警告。
答案 3 :(得分:1)
我认为FluentIterable
(18.0及以上)可以在这方面提供帮助,特别是append
method。
有了这个,我们需要定义一个方便的帮助方法 - 是的,我们将为此使用varargs。
public <T extends Comparable<T>> Set<T> mergeSets(Set<T> initial,
Set<T>... rest) {
FluentIterable<T> result = FluentIterable.from(initial);
for(Set<T> set : rest) {
result = result.append(set);
}
return new TreeSet<>(result.toSet());
}
此处的结果集按自然顺序排列。如果您不想要TreeSet
并且之后不想改变您的收藏,那么请省略new TreeSet<>
段,并放宽T
上的界限。
答案 4 :(得分:0)
如何创建输入集的集合,然后使用flatMap
?
Set<String> allElements = ImmutableSet.of(
One.SET,
Two.SET,
Three.SET
).stream().flatMap(Collection::stream).collect(Collectors.toSet());