I have some Java code that provides objects from items
. It limits them based on the maxNumber
:
items.stream()
.map(this::myMapper)
.filter(item -> item != null)
.limit(maxNumber)
.collect(Collectors.toList());
It works properly, but the question is this: Is there a way of skipping the limiting when the maxNumber == 0
?
I know I could do this:
if (maxNumber == 0) {
items.stream()
.map(this::myMapper)
.filter(item -> item != null)
.collect(Collectors.toList());
} else {
items.stream()
.map(this::myMapper)
.filter(item -> item != null)
.limit(maxNumber)
.collect(Collectors.toList());
}
But perhaps there's a better way, does anything come to your mind?
The skip() MethodThe skip(n) method is an intermediate operation that discards the first n elements of a stream. The n parameter can't be negative, and if it's higher than the size of the stream, skip() returns an empty stream. When this stream is executed, the forEach starts asking for items.
Stream skip(n) method is used to skip the first 'n' elements from the given Stream. The skip() method returns a new Stream consisting of the remaining elements of the original Stream, after the specified n elements have been discarded in the encounter order.
Stream limit(n) is used to retrieve a number of elements from the Stream while the count must not be greater than n. The limit() method returns a new Stream consisting of the elements of the given stream, truncated to be no longer than maxSize in length.
We can create an infinite stream of any custom type elements by passing a function of a Supplier interface to a generate() method on a Stream.
No, the stream pipeline doesn't allow to actually skip around any part of the pipeline, so you're forced to work with either conditional logic inside the steps and including the limit()
always in the pipeline, or building the stream in parts which would be a bit more legible (IMHO) than the if/else in the question
Stream<Item> s = items.stream()
.map(this::myMapper)
.filter(Objects::nonNull);
if(maxNumber > 0) {
s = s.limit(maxNumber);
}
List<Item> l = s.collect(Collectors.toList());
In a simple case like here it doesn't make much difference, but you often see in regular code collections being passed through methods, converted to streams and then back to collections. In such cases it might be a better idea to work with streams in parts until you really need to collect()
.
I suppose that
.limit(maxNumber == 0 ? Long.MAX_VALUE : maxNumber)
will do the trick, as it is highly non probable that you are going to tackle a stream with more than 2^63-1 elements...
At least be careful with parallel streams on this... A note in API docs says:
API Note: While
limit()
is generally a cheap operation on sequential stream pipelines, it can be quite expensive on ordered parallel pipelines, especially for large values of maxSize...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With