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

rwqw0loc  于 2023-03-28  发布在  Java
关注(0)|答案(6)|浏览(979)

我需要将多个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 });
4dbbbstv

4dbbbstv1#

建议使用com.google.common.collect.Sets#union(set1, set2)而不是Set.addAll进行合并,因为Guava已经在您的依赖项中。
原因:是view占用内存,而且不可修改
加:我应该把它作为一个 * 评论 *,对不起。

cbwuti44

cbwuti442#

创建一个输入集的集合,然后使用flatMap怎么样?

Set<String> allElements = ImmutableSet.of(
        One.SET,
        Two.SET,
        Three.SET
).stream().flatMap(Collection::stream).collect(Collectors.toSet());
z4iuyo4d

z4iuyo4d3#

在你之前的尝试中,你写了

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(“unchecked”))

brvekthn

brvekthn4#

您可以用途:

Set<String> set = immutableSetOf(Arrays.asList(One.SET, Two.SET));

使用您对immutableSetOf(List<Set<String>> sets)的定义。没有警告或隐藏的警告。

1wnzp6jl

1wnzp6jl5#

我认为FluentIterable(在18.0和更高版本中)可以在这里提供帮助,特别是append方法。
有了这些,我们需要定义一个方便的helper方法--是的,我们将为此使用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的约束。

gopyfrb3

gopyfrb36#

这应该有助于java8中的. onliner-〉Stream.of(sets).flatMap(Set::stream).collect(Collectors.toSet())

相关问题