我有以下函数用于统一多个集合(包括重复元素):
public static <T> List<T> unify(Collection<T>... collections) {
return Arrays.stream(collections)
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
如果有一个具有类似签名的函数来进行集合的交集(使用类型相等),那就太好了。例如:
public static <T> List<T> intersect(Collection<T>... collections) {
//Here is where the magic happens
}
我找到了 intersect 函数的实现,但它不使用流:
public static <T> Set<T> intersect(Collection<? extends Collection<T>> collections) {
Set<T> common = new LinkedHashSet<T>();
if (!collections.isEmpty()) {
Iterator<? extends Collection<T>> iterator = collections.iterator();
common.addAll(iterator.next());
while (iterator.hasNext()) {
common.retainAll(iterator.next());
}
}
return common;
}
有什么方法可以实现类似于使用流的 unify 函数的东西吗?我对 java8/stream api 不太有经验,因此一些建议会非常有帮助。
您可以在某些实用程序类中编写自己的收集器并使用它:
public static <T, S extends Collection<T>> Collector<S, ?, Set<T>> intersecting() {
class Acc {
Set<T> result;
void accept(S s) {
if(result == null) result = new HashSet<>(s);
else result.retainAll(s);
}
Acc combine(Acc other) {
if(result == null) return other;
if(other.result != null) result.retainAll(other.result);
return this;
}
}
return Collector.of(Acc::new, Acc::accept, Acc::combine,
acc -> acc.result == null ? Collections.emptySet() : acc.result,
Collector.Characteristics.UNORDERED);
}
用法非常简单:
Set<T> result = Arrays.stream(collections).collect(MyCollectors.intersecting());
但请注意,收集器不能短路:即使中间结果是空集合,它仍然会处理流的其余部分。
这样的收藏家很容易在我的免费网站中找到StreamEx https://github.com/amaembo/streamex图书馆(参见MoreCollectors.intersecting() http://amaembo.github.io/streamex/javadoc/one/util/streamex/MoreCollectors.html#intersecting--)。它可以像上面一样与普通流一起使用,但是如果您将它与 StreamEx(它扩展了普通流)一起使用,它就会变得短路:处理实际上可能会提前停止。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)