Many years ago, I took part in the development of a taxi-hailing mobile app that is still widely used today. I don’t know what kind of code they’re running now, but in those early days, the driver assignment code –if I remember it correctly– was similar in spirit to the grossly simplified example th...
This increases the separation of concern in a neat way, and it becomes more clear what the for loop does at a glance (get the first driver satisfying a set of conditions). The more complicated logic is isolated in meetsRiderPreferences, which now only returns true or false. Reading the method is more about making a mental map of a truth table.
It’s also easy to expand the logic (add more filter conditions, sort the drivers based on rating and distance, break out meetsRiderPreferences into smaller methods, etc.).
Not sure how the equivalent in JavaScript would look like, but this is what I would do in Java.
I try to prefer .findAny() over .findFirst() because it will perform better in some cases (it will have to resolve whether there are other matches and which one is actually first before it can terminate - more relevant for parallel streams I think. findAny short circuits that) but otherwise I like the first. I'd probably go with some sort of composed predicate for the second, to be able to easily add new criteria. But I could be over engineering.
I mostly just posted because I think not enough people are aware of the reasons to use findAny as a default unless findFirst is needed.
I would only note that for the vast majority of my experience these streams can only return up to a single match. Determinism isn't really preserved by findFirst, either, unless the sort order is set up that way.
Finding the first Jim Jones in a table is no more reliable that finding any Jim Jones. But finding PersonId 13579 is deterministic whether you findFirst or findAny.
Perhaps you work in a different domain where your experience is different.