reactor hot publisher

Flux Expand vs ExpandDeep with Examples

Overview:

In this tutorial, I would like to show the difference between Flux Expand vs ExpandDeep and simple use cases.  If you are new to project reactor, take a look at all these articles here first for better understanding.

Flux Expand vs ExpandDeep:

In reactive programming, we have subscribers (downstream) and publishers (upstream).  Subscribers request for data. Publishers respond to that. Flux is a publisher which is capable of emitting 0, 1..N items. It is very easy to convert a collection / map into Flux. What if the data structure is hierarchical?  The structure of the data emitted by the publisher could be hierarchical. For example,  a node in the binary tree or a file from the file system or an employee in an organization chart as shown here.

flux expand vs expanddeep

For such data structure, the publisher has to visit and emit items recursively. This is where Flux expand vs expandDeep helps.

Method Search Strategy
expand breadth-first
expandDeep depth-first

Sample Data Structure:

Let’s consider the above organization chart and create a simple Data Structure.

@Data
@NoArgsConstructor
public class Employee {

    private String title;
    private int level;
    private List<Employee> directReports;

    public Employee(String title) {
        this.title = title;
        this.directReports = new ArrayList<>();
    }

    public void addDirectReports(Employee... employees){
        Stream.of(employees).forEach(e -> e.setLevel(this.getLevel() + 1));
        directReports.addAll(List.of(employees));
    }

    @Override
    public String toString() {
        return "\t".repeat(this.level) + this.title;
    }
    
}
  • In the organization chart, every node/person is an employee.
  • The employee might have another employees reporting to them.

Now Let’s create some objects & build the hierarchy.

// CEO - root object
Employee CEO = new Employee("CEO");

// Directors reporting to CEO
Employee directorA = new Employee("Director of Dept A");
Employee directorB = new Employee("Director of Dept B");
CEO.addDirectReports(directorA, directorB);

// Managers reporting to directors
Employee managerA1 = new Employee("Manager 1 of Dept A");
Employee managerA2 = new Employee("Manager 2 of Dept A");
Employee managerB1 = new Employee("Manager 1 of Dept B");
Employee managerB2 = new Employee("Manager 2 of Dept B");
directorA.addDirectReports(managerA1, managerA2);
directorB.addDirectReports(managerB1, managerB2);

With this set up, Let’s see how Flux expand works.

Flux Expand:

I create a simple getDirectReports to get all the direct reporting employees for the given employee as shown here.

private Flux<Employee> getDirectReports(Employee employee){
    return Flux.fromIterable(employee.getDirectReports());
}

For the root object CEO, if we use expand method to recursively visit all the nodes in the hierarchy, we could get below output.

Mono.fromSupplier(() -> CEO)
    .expand(this::getDirectReports)
    .subscribe(System.out::println);

Output:

CEO
    Director of Dept A
    Director of Dept B
        Manager 1 of Dept A
        Manager 2 of Dept A
        Manager 1 of Dept B
        Manager 2 of Dept B

Based on the output, we could understand that expand visits every node & its sibling nodes for a level and then goes to next level to visit all the child nodes until no more item to visit.

Flux ExpandDeep:

Let’s use the same example but change the method to expandDeep.

Mono.fromSupplier(() -> CEO)
    .expandDeep(this::getDirectReports)
    .subscribe(System.out::println);

Output:

CEO
    Director of Dept A
        Manager 1 of Dept A
        Manager 2 of Dept A
    Director of Dept B
        Manager 1 of Dept B
        Manager 2 of Dept B

Based on the output we could understand that expandDeep uses depth-first strategy. That is, for a given node, we visit all its child first before we go to visit sibling nodes. (Goes all the way down & then backtracks).

Flux Expand vs ExpandDeep – Use Cases:

Both Flux Expand and ExpandDeep visit all the nodes until the subscribers cancel. But their visiting order is different and based on that they can be used for different purposes.

Method Use Cases
expand Finding the shortest path in a graph.
Searching file system.
Finding neighbor nodes in a network.
expandDeep Finding all possible combinations.

Summary:

We were able to successfully demonstrate the difference of Flux Expand vs ExpandDeep and understate their behavior.

Learn more on Reactive Programming/Reactive Microservices.

Happy learning 🙂

Reference.

Share This:

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.