This should do the trick:
Set<String> set = new HashSet<>(collection);
boolean containsAll = set.isEmpty() || stream.map(Object::toString)
.anyMatch(s -> set.remove(s) && set.isEmpty());
The solution might look confusing, but the idea is straightforward:
- In order to prevent multiple iterations over
collection
we wrap it into a HashSet
. (In case your stream
is a parallel one, then you will have to use a concurrent hash set. See this post for more details)
- If the
collection
(or set
) is empty then we return true
without processing the stream
- For each entry of
stream
we try to remove it from set
. In case the result of Set::remove
is true
(hence it was contained by set
) and the set
is empty after removal, we can conclude that stream
contained all the elements of initial collection
.
- The terminal operation
Stream::anyMatch
is a short-circuiting one. So it will stop iterating over stream
once the set
is empty. In worst case we will process the entire stream.
Perhaps this is a bit more readable form:
Set<String> set = new HashSet<>(collection);
boolean containsAll = set.isEmpty() || stream.map(Object::toString)
.filter(set::remove)
.anyMatch(__ -> set.isEmpty());
If the collection
can contain duplicates and there is a requirement to check if stream
contains all of them, then we will need to maintain a concurrent map of counters.
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());
The code slightly changed but the idea is the same.
Set<String> temp = source.stream().map(Object::toString).collect(toSet()); boolean containsAll = temp.containsAll(collection);
– Undersignedstream
is lazily generated and not all elements are persisted in the memory. E.g. usingFiles::lines
you can process huge files even though they could not fit in your memory. Collecting into a set will causeOutOfMemoryError
in such a case. – Nonparticipation