Java - 使用流 + lambdas 的多个集合的交集

标签 java collections lambda java-8 java-stream

我有以下功能用于统一多个集合(包括重复元素):

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;
}

有什么方法可以利用流来实现类似于统一功能的功能吗?我在 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 中很容易获得。图书馆(见 MoreCollectors.intersecting() )。它与上面的普通流一起工作,但如果你将它与 StreamEx(扩展普通流)一起使用,它就会短路:处理实际上可能会提前停止。

关于Java - 使用流 + lambdas 的多个集合的交集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42214519/

相关文章:

java - 阿瓦杰伊 bean : Why does it insert object with same ID instead of updating the object?

java - 如何停止 java 执行程序类中的所有可运行线程?

c# - 删除集合中的重复值

java - 将 map 转换为排序列表

c++ - 为什么 Qt 在信号和槽中抛出 lambda 表达式错误?

ruby - 这个例子中 lambda 的目的是什么?

java - Android - 两位小数

java - Tomcat 不呈现 jsp 页面

c# - 哪个更好? DataTable.Select() 或 Linq 用于过滤对象?

c# - 自定义属性和 lambda 表达式