Turn a Stream of Arrays to Single Stream in Java



Occasionally I may include affiliate links, which means I may get a commision if you purchase something via that link. Check out my privacy policy for more info.

Recently I was working with an array of objects where each object itself held an array of different objects. I wanted to go through each of the second items via a Java 8 Stream.

Essentially I had a class that looked something like the following:

public class ArrayHolder {
   public Object[] getArray() {
      return new Object[5];
   }
}

Of course, I had an array of instances of that class:

final ArrayHolder[] holders = {new ArrayHolder(), new ArrayHolder(), new ArrayHolder(), new ArrayHolder()};

I wanted to go through all the items in the second array. Prior to Java 8 and streams, I’d do it with two nested for loops:

for (ArrayHolder holder : holders) {
    for (Object object : holder.getArray()) {
        // do the thing
    }
}

But now, with Java 8, I wanted to do it with streams.

Going through an array via streams is easy enough:

Arrays.stream(holders)

And I can map that stream to the getArray method:

Arrays.stream(holders)
      .map(ArrayHolder::getArray)

But when I go to do something, say, with the forEach method, it wants to do things to the array, not the individual objects:

Arrays.stream(holders)
      .map(ArrayHolder::getArray)
      .forEach(thisIsAnArray -> thisIsAnArray.length);

Initially, I tried to call flatMap, but that didn’t work:

Arrays.stream(holders)
      .flatMap(ArrayHolder::getArray)

This just gives me the following compiler errors:

The method flatMap(Function<? super ArrayHolder,? extends Stream<? extends R>>)
in the type Stream<ArrayHolder> is not applicable for the arguments (ArrayHolder::getArray)

The type of getArray() from the type Main is Object[],
this is incompatible with the descriptor's return type: Stream<? extends R>

It does turn out that flatMap is what I wanted, I just needed to call it after the initial map call. flatMap takes a Stream, so I need to convert the array to a stream… Which I already know how to do, being that’s what I started with:

Arrays.stream(holders)
      .map(ArrayHolder::getArray)
      .flatMap(Arrays::stream);

Now I can totally do things on the individual objects:

Arrays.stream(holders)
      .map(ArrayHolder::getArray)
      .flatMap(Arrays::stream)
      .forEach(thisIsAnObject -> thisIsAnObject.toString());

Fun fact: this works on 2D arrays as well:

Arrays.stream(new Object[2][2])
      .flatMap(Arrays::stream);

Here’s a GitHub Gist I created that demonstrates how to turn the stream of arrays into a single string:

Happy coding!

Leave a Reply

Note that comments won't appear until approved.