Matt Gifford aka coldfumonkeh | Consultant Developer
View Github Profile

Adventures with CBStreams - Reducing and Mixing

Oct 9, 2019

Following on from the two previous posts in the Adventures with CBStreams series, API Transformations and Struct Grouping, today I wanted show you a useful example to use Java streams to reduce a multidimensional array.

Let’s start off with creating a multidimensional array.

In this particular example, we’ll use our musicians again. Let’s consider the first array as modern artists, whilst the second array contains the classics/legends.

If we dump out the arrGroupedData value. we can see the array we need to work with.

The raw multidimnesional array

OK. Let’s start with the native arrayReduce() function. In our code, we simply want to combine the multidimensional array into one array containing all of the values.

The output of the above code shows our single array, fully populated with all of the musicians.

Native CFML arrayReduce

If it does the same thing, why bother using the streams?

Well, we’ve seen in the other posts that streams allow us to manipulate data asynchronously, if we choose. It’s a great choice if you’re dealing with large data sets that you want to process quickly and efficiently.

With that in mind, let’s update our code to replace the native arrayReduce() function with a cbstreams-powered process instead.

The output of the above code is exactly the same as the native arrayReduce() method.

A great reason to use streams to reduce your arrays is the ability to run additional processes on the values prior to returning the complete reduction.

The value from the first map() function is each sub-array included within the parent - our modern and classic artists respectively.

We can take that sub-array and send it through the pipeline, adding a second map() function. We’ll pass that array through to an external function, artistDetailStream(), which will send off a request to the Spotify Web API to receive information for that artist, searching by the given name.

objSpotify relates to a variable assignment for the Spotify Web API component, not included here as it contains oauth-related information as part of the constuctor. We also pass through the instantiated streamBuilder component into the artistDetailStream() function.

As the initial parameter we send through is an array of structs containing artist names, we still have to loop over the array to send each name to the API.

We can run this process asynchronously by using, you guessed it, Java streams.

Once again, we set up a new Java stream within the function, looping over the number of records within the given array and pulling each item out using the first map() function.

The second map() now receives the struct containing the actual name of the artist, and it is that value we can use to send to the Spotify API to run a search.

We then obtain the first relevant match from the available items in the API response and create a struct of data to set into our array to pass back to the original calling process.

You can also see that we ran this procedure asynchronously using the parallel() method to help speed up the overall response.

This transformed response is returned in the original requesting stream process, and the results are combined into a single array as before, only this time with more data pulled from an external API.

The reduced and transformed array

Just in case it passed you by, we are running a Java stream WITHIN another Java stream.

How cool is that?

Latest Blog Posts

Jul 16, 2020
Github Actions with CommandBox and TestBox
Read More
Jul 9, 2020
Azure pipelines with CommandBox and TestBox
Read More
Dec 23, 2019
CFML content moderation detection component library
Read More