List integer = Stream.generate(new Supplier() {
int i = 0 ;
@Override
public Integer get() {
return ++i;
}
}).
Flipping the limit
and the filter
clauses has different behaviors.
If you put the limit
first, the stream will first generate 10 integers [1..10], and then filter them leaving only those smaller than 5.
In the original ordering, with the filter
applied first, integers are generated and filtered until you reach 10 elements. This isn't an infinite operator, as i
in the supplier will eventually overflow, but it will take a while, especially on a slow computer, to reach MAX_INT
.
If you want to stop either if number 5 is reached or 10 elements are collected, there's Stream.takeWhile()
method added in Java-9:
List<Integer> integer = Stream.generate(new Supplier<Integer>() {
int i = 0 ;
@Override
public Integer get() {
return ++i;
}
}).takeWhile(j -> j < 5).limit(10).collect(Collectors.toList());
It will finish, after the Supplier overflows and starts generating negative numbers. The resulting list will contain:
[1, 2, 3, 4, -2147483648, -2147483647, -2147483646, -2147483645, -2147483644, -2147483643]
The reason for this is in other answers. On my i7 machine it took 40 seconds to complete.
Since there are only 4 elements that pass the filter, limit(10)
never reaches 10 elements, so the Stream pipeline keeps generating new elements and feeding them to the filter, trying to reach 10 elements that pass the filter, but since only the first 4 elements pass the filter, the processing never ends (at least until i
overflows).
The Stream pipeline is not smart enough to know that no more elements can pass the filter, so it keeps processing new elements.