如何在Java中将多个(任意数量的)Set <String>合并为一个?

Jan*_*yne 3 java collections guava

我有多个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");
}
Run Code Online (Sandbox Code Playgroud)

现在,我需要将这些集合的任意组合合并为一个.例如,我可能需要合并

  • 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文章在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);
}
Run Code Online (Sandbox Code Playgroud)

这是调用代码; 它不起作用(不编译).

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

所以,我修改了我的合并方法来操作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);
}
Run Code Online (Sandbox Code Playgroud)

所以,现在我的调用代码如下所示.

Set<String> set = Utils.immutableSetOf(
 Lists.newArrayList(
  One.SET, Two.SET));
Run Code Online (Sandbox Code Playgroud)

此代码无法编译,因为Lists.newArrayList(...)返回Set<String>而不是List<Set<String>>.该方法Lists.newArrayList(...)被重载,并且当我传入集合时使用的方法的签名是,List.newArrayList(Iterable<? extends E> elements).

所以,问题是,如何Set<String>在考虑调用代码的同时定义合并任意数量的方法?我注意到编译问题是在调用代码(而不是合并方法)上,但也许解决方案也与合并代码有关?

更新:我也尝试了varargs但是会产生自己的警告(是否有可能解决"为varargs参数创建T的通用数组"编译器警告?).合并方法签名现在如下.

public static Set<String> immutableSetOf(Set<String>... sets)
Run Code Online (Sandbox Code Playgroud)

调用代码现在如下,我得到"类型安全:为varargs参数创建Set的通用数组".

Set<String> set = Utils.immutableSetOf(One.SET, Two.SET);
Run Code Online (Sandbox Code Playgroud)

更新:对于接受的答案,我做了以下操作.

@SuppressWarnings("unchecked")
Set<String> set = Utils.immutableSetOf(Set[] { One.SET, Two.SET });
Run Code Online (Sandbox Code Playgroud)

卢声远*_* Lu 6

建议com.google.common.collect.Sets#union(set1, set2)获取合并而不是Set.addAll引擎盖,因为Guava已经在您的依赖项中.

原因:它的视图是记忆有效的,也是不可修改的.

加:我应该发布评论,抱歉.


MJS*_*JSG 2

在你之前的尝试中,你已经写过

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

这不起作用,因为 java 中不允许创建泛型数组

尝试这个:

@SuppressWarnings("unchecked")
Set<String>[] mySet = new Set[] { One.SET, Two.SET };
Set<String> set = Utils.immutableSetOf(mySet);
Run Code Online (Sandbox Code Playgroud)

这样做的原因是,我们创建一个新的 Set[] 而不指定泛型类型并将其分配给引用 Set[] mySet (因为这是一个未经检查的操作,我们必须向其添加 @SuppressWarnings("unchecked") )