'What is the fastest way to iterate on a stream in Java 8?
If I have a collection and I want to iterate over a filtered stream then I could do either of the following (and many more obtuse options):
for(item in collection.stream().filter(...).collect(Collectors.toList()))
for(item in collection.stream().filter(...).collect(Collectors.toSet()))
Which is faster? A list or a set? Is there some way to collect to simply an Iterable or some other type I can iterate on?
Solution 1:[1]
If you only want to iterate over the elements of the Stream
, there's no need to collect it into a Collection
, just use forEach
:
collection.stream()
.filter(...)
.forEach (item -> {
// do something with item
}
);
Solution 2:[2]
If you don't care about elements order use parallelStream:
collection.parallelStream().filter(...).forEach(...)
This way you iterate through the collection using more threads.
To mesure which stream or parallelStream procesing is faster for a specific case review @Brian Goetz answer for the related problem
Solution 3:[3]
Is there some way to collect to simply an Iterable or some other type I can iterate on?
If for some reason you did want to use a Stream
as the target of a for-each
loop, you don't have to collect it:
for (Item item : (Iterable<Item>)
coll.stream().filter(...)::iterator) {
}
or:
Iterable<Item> iter = coll.stream().filter(...)::iterator;
for (Item item : iter) {
}
This works because Iterable
is a functional interface, even though it is not annotated as such.
It's just an interesting thing to know about, though. forEach
as Eran has suggested is probably the 'right' way to go about things in general. The java.util.stream
package description describes iterator
as an "escape hatch".
Solution 4:[4]
If performance is what you are aiming at, don't use streams at all. Streams are nice, but they are almost always slower than plain old java iteration.
What is then the fastest depends a bit on the situation. If it is pure for iterating, then ArrayList outperforms HashSet. The fastest way to iterate over an ArrayList is not the for-each loop, but the plain old i-iteration:
int size = list.size();
for (int i = 0; i < size; i++) {
...list.get(i)...
}
Make sure that you read the size outside of the loop to a local variable, otherwise you get many unnecessairy calls to list.size().
If you need filtering the original list, just adding some if inside this loop is almost always faster than using streams with filter.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Community |
Solution 3 | |
Solution 4 | Rinke |