Limit a Stream by a Predicate

Limit a stream by a predicate

Operations takeWhile and dropWhile have been added to JDK 9. Your example code

IntStream
.iterate(1, n -> n + 1)
.takeWhile(n -> n < 10)
.forEach(System.out::println);

will behave exactly as you expect it to when compiled and run under JDK 9.

JDK 9 has been released. It is available for download here: JDK 9 Releases.

Stream generate until a limit but only matching a predicate

Like this:

List<Integer> list = Stream.generate(new Random()::nextInt)
.filter(p -> p > 10)
.limit(100).collect(Collectors.toList());

Or like this one:

public class Main {

private static boolean isBig(Integer input) {
return input > 10;
}

public static void main(String args[]) {
List<Integer> list = Stream.generate(new Random()::nextInt)
.filter(Main::isBig)
.limit(100).collect(Collectors.toList());
}
}

Can I count my stream size if I limit it by a predicate dependent on the input?

Java 9 has a feature to support that - takeWhile:

random.ints(0, Integer.MAX_VALUE).takeWhile(a -> a < 20000).count();

Is there a way to stop Stream.iterate() with a predicate?

Using Java-9 or above, one way is to use Stream.takeWhile as:

Stream.iterate(1, i -> i * 2) // notice identity value in seed
.takeWhile(i -> i < MAX)

Another alternative is to use Stream.iterate

Stream.iterate(1, i -> i < MAX, i -> i * 2)

Limit a stream and find out if there are pending elements

I don't think there's a nice way to do this. I've found a hack that does it lazily. What you can do is convert the Stream to an Iterator, convert the Iterator back to another Stream, do the Stream operations, then finally test the Iterator for a next element!

Iterator<SomeResource> it = this.someResource().iterator();
List<String> list = StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.ORDERED), false)
.filter(resource -> !resource.isTaken())
.limit(MAX_TO_RELEASE)
.peek(SomeResource::release)
.map(SomeResource::getName)
.collect(Collectors.toList());
return new ReleaseResult(list, it.hasNext(), MAX_TO_RELEASE);

jenetics: Set EvolutionStream limit outside of stream()

The EvolutionStream.limit(Predicate) method does return an EvolutionStream.

EvolutionStream<IntegerGene, Double> stream = engine.stream();
stream = stream
.limit(Limits.byFixedGeneration(10))
.limit(Limits.bySteadyFitness(5))
.limit(Limits.byExecutionTime(Duration.ofMillis(100)));

So your given examples look good and should work. But the EvolutionStream.limit(Predicate) method is the only method which gives you back an EvolutionStream.

An alternative would be that your method, which initializes the EvolutionStream, takes the Predicates from outside.

@SafeVarargs
static EvolutionStream<IntegerGene, Double>
newStream(final Predicate<? super EvolutionResult<IntegerGene, Double>>... limits) {
final Engine<IntegerGene, Double> engine = Engine
.builder(a -> a.gene().allele().doubleValue(), IntegerChromosome.of(0, 100))
.build();

EvolutionStream<IntegerGene, Double> stream = engine.stream();
for (var limit : limits) {
stream = stream.limit(limit);
}

return stream;
}

final var stream = newStream(
Limits.byFixedGeneration(100),
Limits.byExecutionTime(Duration.ofMillis(1000)),
Limits.bySteadyFitness(10)
);

What happens if I'll call limit() after filter() from Stream API?

filter() has lazy execution. This means that it doesn't actually do anything right when you call it. Instead it just returns a new Stream that will contain the elements that match the given Predicate when traversed.

Since limit() is a short-circuiting stateful intermediate operation, it will process the Stream until it reaches the limit and short circuits. This means that when you call filter, it will return a new Stream that contains only the elements, when traversed. Since limit only traverses enough to reach the given size, filter will, in effect, only filter out the required amount of elements.

We can test this by throwing in a call to peek():

Arrays.stream(new int[] {1, 2, 2, 2, 2})
.filter(e-> e > 1)
.peek(System.out::println)
.limit(3)
.average();

(Where average() could be any terminal operation that doesn't short circuit on its own)

Which outputs:

2
2
2

(Note that the last two does not appear after the call to filter())

Java IntStream or LongStream limit by value and not by count of elements

In Java 9+, use takeWhile(i -> i <= value).



Related Topics



Leave a reply



Submit