Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How could collateral effects be managed in Java8 streams

I understand that Streams in Java8 can only be collected once (as in a forEach() termination) but I'm wondering if we could manage to "tap" into a stream in the middle of a chain of filtering and mapping tasks to produce some collateral effect.

In essence, "tapping" would be like doing a forEach() but returning the Stream at that point of the pipeline.

I'd use it like this:

List<User> createAndPersistRandomUsers(int count) {
  return IntStream.range(0, count)
    .boxed() // returns Stream<Integer>
    .map(UserBuilder::random) // returns Stream<User>
    .tap(userRepo::persist) // Collateral persist of user, returns Stream<User>
    .collect(toList()); // returns List<User>
}

Any ideas?

like image 282
ggalmazor Avatar asked Feb 19 '15 11:02

ggalmazor


1 Answers

The closest thing I can think of to achieve what you want is peek :

Stream peek(Consumer action)

Returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream.

This is an intermediate operation.

It allows you to perform an action on an element of the Stream while the Stream in being consumed.

List<User> createAndPersistRandomUsers(int count) {
  return IntStream.range(0, count)
    .boxed() // returns Stream<Integer>
    .map(UserBuilder::random) // returns Stream<User>
    .peek(userRepo::persist) // Collateral persist of user, returns Stream<User>
    .collect(toList()); // returns List<User>
}
like image 186
Eran Avatar answered Oct 05 '22 06:10

Eran