java - 有没有办法检查 Stream 是否包含所有集合元素?

标签 java collections java-8 java-stream contains

例如,我需要这样的东西:

Collection<String> collection = /* ... */;
Stream<Object> stream = /* ... */;
boolean containsAll = stream.map(Object::toString).containsAll(collection);

当然,我可以使用 collect() 方法和调用 Collection.containsAll() 将流的所有元素累积到另一个 Collection >,但是如果流太大并且处理它的所有元素效率低下怎么办?

最佳答案

这应该可以解决问题:

Set<String> set = new HashSet<>(collection);
boolean containsAll = set.isEmpty() || stream.map(Object::toString)
                                             .anyMatch(s -> set.remove(s) && set.isEmpty());

解决方案可能看起来令人困惑,但想法很简单:

  1. 为了防止对collection 进行多次迭代,我们将其包装到HashSet 中。 (如果您的 stream 是并行的,那么您将不得不使用并发哈希集。有关详细信息,请参阅 this post)
  2. 如果 collection(或 set)为空,则我们返回 true 而不处理 stream<
  3. 对于 stream 的每个条目,我们尝试将其从 set 中删除。如果 Set::remove 的结果是 true(因此它包含在 set 中)并且 set删除后为空,我们可以得出结论 stream 包含初始 collection 的所有元素。
  4. 终端操作Stream::anyMatch 是一个短路操作。因此,一旦 set 为空,它将停止遍历 stream。在最坏的情况下,我们将处理整个流。

也许这是一种更具可读性的形式:

Set<String> set = new HashSet<>(collection);
boolean containsAll = set.isEmpty() || stream.map(Object::toString)
                                             .filter(set::remove)
                                             .anyMatch(__ -> set.isEmpty());

如果 collection 可以包含重复项,并且需要检查 stream 是否包含所有重复项,那么我们将需要维护一个并发计数器映射。

Map<String, AtomicLong> map = new ConcurrentHashMap<>();
collection.forEach(s -> map.computeIfAbsent(s, __ -> new AtomicLong()).incrementAndGet());
boolean containsAll = map.isEmpty() || stream.map(Object::toString)
                                             .filter(map::containsKey)
                                             .filter(s -> map.get(s).decrementAndGet() == 0)
                                             .filter(s -> map.remove(s) != null)
                                             .anyMatch(__ -> map.isEmpty());

代码略有变化,但思路是一样的。

关于java - 有没有办法检查 Stream 是否包含所有集合元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58269632/

相关文章:

java - 隐式类型转换不应该从 char 到 String。这怎么可能 ?

java - "Exception in thread "主要 "java.lang.NoSuchMethodError "

java - 访问隐藏在第三个扩展类中的间接父类(super class)变量

java - TreeMap 的数据发生了奇怪的变化

java - 为什么listiterator只为List设计,而Set不是?

gradle - NoClassDefFoundError GradleBuild智能

java - 字符串数组声明的差异。 String[] foo 或 String foo[]

java - 实现 java.util.Collection<E> 和重写方法时出现问题

java - 将字符串日期转换为 ISO 格式日期

java -/etc/timezone 在 anapsix/alpine-java :8_server-jre docker image 上不存在