I have this code:
return myList
.stream()
.filter(Objects::nonNull)
.filter(listItem -> {
try {
return listItem.matchesCondition();
} catch (Exception e) {
// log error
return false;
}
})
.findFirst()
.map(listItem -> {
try {
return listItem.getResult();
} catch (Exception e) {
// IF THIS HAPPENS, HOW CAN WE ADVANCE TO THE NEXT ITEM IN THE STREAM.
// I'M ASSUMING WE CAN NOT SINCE THE STREAM WAS TERMINATED BY findFirst.
// BUT HOW CAN I WRITE THIS IN A DIFFERENT WAY TO ACHIEVE THAT BEHAVIOR?
// log error
return null;
}
});
The issue is, if the first matching listItem throws an exception in the map function, an empty Optional is returned.
But instead, I want to continue testing the remaining items in the list, and try to map the next one that matches the filter.
How can I do that with streams and lambdas?
I can convert to this more imperative code but would like to find a functional solution.
for (MyListItem myList : listItem) {
try {
if (listItem.matchesCondition()) {
return Optional.of(listItem.getResult());
}
} catch (Exception e) {
// SWALLOW THE EXCEPTION SO THE NEXT ITEM IS TESTED
// log error
}
}
return Optional.empty();
You have to move the findFirst
to the very end, because it reduces the stream to just (at most) a single element and you cannot "go back" and get more after that.
return myList
.stream()
.filter(Objects::nonNull)
.filter( ... )
.map( ... ) // returns null on Exception, so filter again
.filter(Objects::nonNull)
.findFirst()
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