The main problem is that the inner loop body
if (cond(outer, inner))
func(outer, inner);
else
moo(outer, inner);
has no counterpart in the Stream API and remains a single opaque action for most thinkable solutions, so the simplest solution is to express it as a Consumer which you invoke using a nested forEach, which offers no benefit to the nested for loop you already have.
If you want to enforce a flatMap based solution, you can do the following:
owner.getOuterList().stream().flatMap(
outer -> owner.getInnerList().stream().<Runnable>map(
inner -> cond(outer, inner)? () -> func(outer, inner): () -> moo(outer, inner))
).forEach(Runnable::run);
It doesn’t need a Pair/Tuple type for mapping to [outer,inner] as the functions themself are capable of capturing these values. Note that this will evaluate the condition in the inner stream processing but the actual invocation of either func or moo will happen in the outer stream processing. You can enforce processing everything within the outer stream with
owner.getOuterList().stream().flatMap(
outer -> owner.getInnerList().stream().<Runnable>map(
inner -> () -> { if(cond(outer,inner)) func(outer,inner); else moo(outer,inner); })
).forEach(Runnable::run);
which, as said, treats your original inner loop’s body like an opaque action.
I think, it’s clear that neither is a real win over the original nested for loop here.
.flatMap(outer -> owner.getInnerList().stream().map(inner -> new Object[] { outer, inner }))The issue is always having a Tuple class for holding bothinnerandouter. Here since they are bothObject, we could abuse an array... All in all: keep theforloop.