Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 是否有方法检查流是否包含所有集合元素?_Java_Collections_Java 8_Java Stream_Contains - Fatal编程技术网

Java 是否有方法检查流是否包含所有集合元素?

Java 是否有方法检查流是否包含所有集合元素?,java,collections,java-8,java-stream,contains,Java,Collections,Java 8,Java Stream,Contains,例如,我需要以下内容: Collection<String> collection = /* ... */; Stream<Object> stream = /* ... */; boolean containsAll = stream.map(Object::toString).containsAll(collection); Collection=/*…*/; Stream=/*…*/; 布尔containsAll=stream.map(对象::toString.c

例如,我需要以下内容:

Collection<String> collection = /* ... */;
Stream<Object> stream = /* ... */;
boolean containsAll = stream.map(Object::toString).containsAll(collection);
Collection=/*…*/;
Stream=/*…*/;
布尔containsAll=stream.map(对象::toString.containsAll(集合);

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

无论
流有多大,如果它不包含
集合的所有元素,则必须处理它的所有元素

如果
的一个小前缀包含
集合
的所有元素,并且
集合
小得多,则可以节省处理时间

boolean containsAll = 
    stream.map(Object::toString)
          .filter(s -> collection.contains(s)) // it would be wise to convert collection to a Set
          .limit(collection.size())
          .count() == collection.size();

请注意,如果
可能包含
集合
的同一元素的多个副本,您可能需要在
过滤器()后添加
.distinct()
操作,这应该可以做到:

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

如果
集合
可以包含重复项,并且需要检查
是否包含所有重复项,那么我们需要维护计数器的并发映射

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());
Map Map=new ConcurrentHashMap();
collection.forEach->map.computeIfAbsent(s,_u->new AtomicLong()).incrementAndGet();
布尔containsAll=map.isEmpty()| | stream.map(对象::toString)
.filter(映射::containsKey)
.filter->map.get.decrementAndGet()=0
.filter->map.remove!=null)
.anyMatch(_->map.isEmpty());
代码略有变化,但想法是一样的

boolean allMatch = stream.map(Object::toString)
            .allMatch(s -> collection.contains(s));  

allMatch方法的工作原理与anyMatch类似,但将检查流的所有元素是否与给定谓词匹配。

集合创建一个集合
,以加快搜索操作
O(1)

另一种方法是通过不包含在集合中进行过滤,并使用
限制(1)
进行优化

boolean isContains = stream.map(Object::toString)
                           .filter(s -> !set.contains(s))
                           .limit(1)
                           .count() > 0;

就我个人而言,我认为使用
settemp=source.stream().map(Object::toString.collect(toSet());布尔containsAll=临时containsAll(集合)@OusmaneD。如果流像OP假设的那样太大怎么办?想象一下,当
是惰性生成的,并且不是所有元素都持久存在内存中时的情况。例如,使用
文件::行
您可以处理大型文件,即使它们无法放入您的内存。在这种情况下,收集到集合中会导致
OutOfMemoryError
。在这种情况下,不使用
collect
比任何其他操作(
count
)的好处我真的不太明白。由于对完整元素的流处理无论如何都会发生(最坏的情况),是否有可能进行优化以避免占用那么多内存?@Naman如果流有1000000个元素,但集合的所有元素都出现在流的前50个元素中,它会处理所有元素吗?当然,如果不是集合的所有元素都出现在流中(或者如果最后一个元素出现在流的末尾附近),这个解决方案将不会有帮助?如果对流和集合进行排序,处理containsAll会更快吗?@Eran By containsAll我指的是您的方法,查找集合是否包含流的所有元素。谢谢你的澄清。@Paul我误解了你的问题。如果对流和集合进行了排序,那么即使流不包含集合的所有元素,也应该能够生成一个有效的解决方案(不处理整个流),因为我们可以确定流中的某个点,在该点之后不再有属于集合的元素。这可以通过
takeWhile
完成。似乎您还可以将其包装在
列表中
以支持检查流是否包含元素的多个实例<代码>列表。删除
将返回true,直到删除所有副本。@SeanVanGorder实际上,这是一个非常有趣的案例。为了简单起见,我在解决方案中忽略了这一点。但是使用
List
我们将失去
HashSet
提供的性能提升。在这种情况下,您只需检查原始集合是否是
Set
并将其包装在
HashSet
中,而不是
ArrayList
。这种映射计数预处理似乎是一种折衷,对于大型非
Set
集合可能更快,但对于小型集合可能更糟。这是有道理的。编程是一种权衡。不同的数据结构适用于不同的情况。软件工程师仍然需要选择一个更适合他/她试图解决的任务的软件。这让我大吃一惊。我从没想过如果像这样使用流。谢谢。来自一名大学生这并没有正确回答问题,它检查流的所有元素是否都包含在集合中,问题询问集合的所有元素是否都在流中。
Set<String> set = new HashSet<>(collection);
boolean containsAll = stream.map(Object::toString)
                            .allMatch(s -> set.contains(s));
boolean isContains = stream.map(Object::toString)
                           .filter(s -> !set.contains(s))
                           .limit(1)
                           .count() > 0;