Java streaming higher order function

wearebob :

I am trying to process an object that has nested lists 2 levels deep. For example my object can be broken down to something like this:

TopLevel: [
    MidLevel: [
        LowLevel,
        LowLevel,
        .
        .
    ],
    MidLevel: [
        LowLevel,
        LowLevel,
        .
        .
    ]
    .
    .
]

Essentially TopLevel contains a list of MidLevel objects, which in turn each contain a list of LowLevel objects. At the end of the processing I would like to build SomeObj for each of the LowLevel objects. However SomeObj requires information from TopLevel, MidLevel, and LowLevel.

I have been trying to write code in a more functional style over the last several months so my first thought was to create a higher order function that I could build up over each level in the object. The function looks like this:

Function<MidLevel, Function<LowLevel, SomeObj>> buildObjects(TopLevel topLevel) {
    return midLevel ->
        lowLevel -> {
            return buildSomeObj(topLevel, midLevel, lowLevel);
        };
}

I intend to use this function in some way like the following (assume I have utility functions that provide a stream of the lists):

Function<MidLevel, Function<LowLevel, SomeObj>> topBuilder = buildObjects(topLevel);
List<SomeObj> objs = topLevel.streamMid()
    .map(topBuilder)
    .streamLow()
    .map(Function::apply)
    .collect(/*collect to list*/);

However, this obviously does not work because once I apply the MidLevel objects to the topBuilder function my stream is now a stream of functions and not MidLevel objects, thus I do not have access to the list of LowLevel objects in the stream anymore.

Is there any solution to this or am I trying to solve this functionally when it's not well suited to it? Is there a way to both apply the function, and also have access to the original object that was applied to that function?

Thomas :

flatMap() and nesting are the way to go. Try this:

topLevelStream() //create a stream of top level elements
  .flatMap( top -> top.streamMid() //create a stream of mid level elements
    .flatMap( mid -> mid.streamLow() //create a stream of low level elements
      .map(low -> "use top, mid and low here") 
    ) 
  )
  .collect( ... );

By nesting like this you still have access to the elements in the outer functions and the combination of flatMap() and map() exposes the stream that map() is called upon to collect().

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=75140&siteId=1