Why two .map operations? Three reasons.
#1- If I'm dealing with some legacy code that I don't know well, and it's mapping from one object to a property of it that is another object... well, I'm not 100% certain it's not null.
.map(a -> a.getB())
.map(b -> b.getC())
if a.getB() is null, Optional eats it and I'm safe from NPE- I just an a non present Optional value. .map(a -> a.getB().getC())
If B is null, I'm going to NPE here (... right? I'm like 99% sure of that, but correct me please). And there are counter arguments like "never be null", etc, but I've got legacy code to cleanup, and no one taught the person who wrote it that particular lesson.#2- Ease of understanding. Little jumps rather than big ones. Makes the code easier to understand for the next guy who has to work on it. As much as I can, I try to write code that requires no commenting- because it's so clean it's not needed.
#3- The compiler will (or will eventually) optimize it into a single map anyways. Compilers are smart and keep getting smarter. So long as my big-O runtime is fine, I just focus on ease of understanding of my code.
>Two .map-s one after another is code smell (and also a bit slow). Why not combine them into one?
I believe they are automatically combined before the results of the stream are forced.
Do standard collections have groupBy? You can go a long way with groupBy and zipWith operations, which are a pair like map-reduce but for in-memory handling.