Motivation:
.flattenLast() presumes the last argument is the collection to flatten. But it could be the first argument, or a property of the any argument, or a list calculated from 2 arguments.
Proposal:
provide a lambda method to the flatten() so the user can figure it out themselves
Strawmans:
Uni:
forEach(Shift) // Uni<Shift>
.flatten(shift -> shift.getRequiredSkills)) // Bi<Shift, Skill>
Bi:
forEach(Shift).join(Day, overlapping(...) // Bi<Shift, Day>
.flatten((shift, day) -> extractOverlappingHours(shift, day)) // Tri<Shift, Day, Hour>