1. Overview

Sometimes in Reactive Programming, we could have a publisher of a large collection of items. In some cases, consumers of this publisher might not be able to process all items in one go. Therefore, we may need to publish each item asynchronously to match the consumer's processing speed.

In this tutorial, we'll be looking into some ways by which we can convert our Mono of a Collection to Flux of Collection's items.

2. Problem Description

When working with Reactive Streams, we use a Publisher and its two implementations, Flux and Mono. Though Mono<T> is a type of Publisher<T> that can emit 0 or 1 item of type T, the Flux<T> can emit 0 to N items of type T.

Let's say we have a Mono publisher that is holding a Mono<List<T>> — an iterable collection of items of type T. Our requirement is to produce the collection items asynchronously using Flux<T>:

Here, we can see that we need an operator on Mono<List<T>> that can perform this transformation. First, we'll extract collection items from stream publisher Mono and then produce items one by one asynchronously as Flux.

The Mono publisher contains a map operator, which can transform a Mono synchronously, and a flatMap operator for transforming a Mono asynchronously. Also, both of these operators produce a single item as an output.

However, for our use case to produce many items after flattening Mono<List<T>>, we can use flatMapMany or flatMapIterable.

Let's explore how to use these operators.

3. flatMapMany

Let's start with a sample List of String to create our Mono publisher:

private Mono<List<String>> monoOfList() {
    List<String> list = new ArrayList<>();
    list.add("one");
    list.add("two");
    list.add("three");
    list.add("four");

    return Mono.just(list);
}

The flatMapMany is a generic operator on Mono that returns a Publisher. Let's apply flatMapManyto our solution:

private <T> Flux<T> monoTofluxUsingFlatMapMany(Mono<List<T>> monoList) {
    return monoList
      .flatMapMany(Flux::fromIterable)
      .log();
}

In this case, the flatMapMany takes the Mono‘s List, flattens it, and creates a Flux publisher using Flux operator the fromIterable. We also used log() here to log each element produced. Therefore, this will output elements one by one like “one“, “two“, “three“, “four“, and then terminate.

4. flatMapIterable

For the same sample List of String, we'll now explore flatMapIterable — a custom-built operator.

Here, we don't need to create Flux explicitly from the List; we only need to provide the List. This operator implicitly creates a Flux out of its elements. Let's use flatMapIterable for our solution:

private <T> Flux<T> monoTofluxUsingFlatMapIterable(Mono<List<T>> monoList) {
    return monoList
      .flatMapIterable(list -> list)
      .log();
}

Here, flatMapIterable takes the Mono‘s List and converts it internally into a Flux of its elements. Hence, it's more optimized compared with the flatMapMany operator. And this will output the same “one“, “two“, “three“, “four“, and then terminate.

5. Conclusion

In this article, we discussed different ways to convert a Mono<List<T>> into Flux<T> using the operators flatMapMany and flatMapIterable. Both are easy-to-use operators. Whereas flatMapMany is useful for more generic publishers, flatMapIterable is better optimized for such purposes.

As always, the code example is available over on GitHub.

Generic bottom

Get started with Spring 5 and Spring Boot 2, through the Learn Spring course:

>> CHECK OUT THE COURSE
Comments are closed on this article!