Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to define an optional flow or exception-like behaviour in Java 8 streams API?

Let us have a stream of objects, resulting from a sequence of operations (e.g. mapping, filtering, flatmapping, etc.). Now I want to do a certain operation on them, but only if a given predicate is true. Otherwise I want to immediately return something else.

A simple example. I have a stream of different food objects. If all of them are edible I want to perform a cook operation on them and return the list of cooked food. But if any of them turns out to not be edible I want to immediately return an empty list.

Few solutions come to my mind, but I am not satisfied with any of them.

I could first perform an allMatch operation with isEdible predicate on the stream, but it will result in terminating it and I would need to repeat preliminary operations once more.

I could persist the collection that is the result of preliminary operations before checking the edibility, but therefore I need to perform them for all elements. Which is suboptimal, because it may turn out, that the first of them is not edible and allMatch would return much, much earlier.

Or I could design a hacky reduce routine, but it would also be unable to stop processing elements when predicate fails.

What I hope for is something like the code below. Is it possible with current API?

source.stream()
    // some operations
    .ifAny(food -> !food.isEdible(), new LinkedList<Food>())
    // other operations if previous step not failed
    .peek(food -> food.prepare())
    .collect(Collectors.toList());
like image 214
Radosław Łazarz Avatar asked Oct 18 '22 04:10

Radosław Łazarz


1 Answers

Not exactly what you wanted, but using the ternary operator will make your two step solution look cleaner, it also should have optimal performance:

return source.stream()
    .allMatch(this::isEdible)
    ? source.stream()
        .map(this::prepare()) // do stuff
        .collect(Collectors.toList())
    : Collections.emptyList();
like image 114
Journeycorner Avatar answered Oct 21 '22 08:10

Journeycorner