Switch-case and If-else blocks in Rx-Java streams

Switch-case and If-else blocks in Rx-Java streams

One thing that we miss in Reactive Extensions (Rx...) is the flow control operators, if we need to do different behaviors bases on the emitted items, we have to make those ugly If-Else or Switch-Case blocks inside a flatMap() or whatever operator ... a similar case to this is as follows :

List<Integer> list = Arrays.asList(1, 2, 3, 4);

Observable.fromIterable(list)
        .flatMap(integer -> {
            switch (integer) {
                case 1:
                    return Observable.just("First Odd Number : " + integer);
                case 2:
                    return Observable.just("First Even Number : " + integer);
                default:
                    return Observable.empty();
            }
        }).subscribe(System.out::println);

Of course this sample is just for clarification, it is not about even and odd numbers ... a better way to do the same code snippet in a more readable and modular way, is to use a "SwitchCase" operator :

Map<Integer, Function<Integer, String>> caseBlocks = new HashMap<>(2);
caseBlocks.put(1, (integer) -> "First Odd Number : " + integer);
caseBlocks.put(2, (integer) -> "First Even Number : " + integer);

List<Integer> list = Arrays.asList(1, 2, 3, 4);

Observable.fromIterable(list)
        .lift(new SwitchCase<>(caseBlocks))
        .subscribe(System.out::println);
 
  

Both code snippets do the same thing, but the main difference is the "readability" , the second snippet reduced the Control Coupling between the Rx-Java stream and the outside world ... it takes a bunch of functions in a map, if any key in this map is equal to the emitted item, it will execute what ever function it finds, imagine if this map is injected from out side, like as follows :

public MyObject(Map<Integer, Function<Integer, String>> caseBlocks){

    List<Integer> list = Arrays.asList(1, 2, 3, 4);
    Observable.fromIterable(list)
            .lift(new SwitchCase<>(caseBlocks))
            .subscribe(System.out::println);
}

Now we have our Rx-Java stream free of Switch-case blocks, the stream code does not depend on external values to determine how to continue the down stream, it receives a Map and this map holds these values and functions ... we decoupled the flow control from our stream

If we want to emit the ONLY first item that matches our condition, we may implement this as follows :

Observable.fromIterable(list)
        .flatMap(integer -> {
            switch (integer) {
                case 1:
                    return Observable.just("First Odd Number : " + integer);
                case 2:
                    return Observable.just("First Even Number : " + integer);
                default:
                    return Observable.empty();
            }
        })
        .firstElement()
        .subscribe(System.out::println);

Now instead of adding extra operation, which is firstElement(), we can use "SwitchCaseBreak" :

Map<Integer, Function<Integer, String>> caseBlocks = new HashMap<>(2);
caseBlocks.put(1, (integer) -> "First Odd Number : " + integer);
caseBlocks.put(2, (integer) -> "First Even Number : " + integer);

List<Integer> list = Arrays.asList(1, 2, 3, 4);

Observable.fromIterable(list)
        .lift(new SwitchCaseBreak<>(caseBlocks))
        .subscribe(System.out::println);
 
  


The SwitchCase and SwitchCaseBreak operators source code can be fount at the following link, you can add a version that takes a Predicate as a key instead of an Object of type "T", if you need comparison other than "equals()" method.


Aleksander Krapivny

Lead Android Software Engineer

6y

Best!

Like
Reply
Mohamed Elgendy

Software Engineering Lead at Zalando SE

7y

This is very helpful for rx users

Abdulrahman Rudwan

Lead Engineer || FinTech || Digital Banking || SAAS

7y

يا ابوحميد انا حبيت ال Rx بسبب كلامك عنها 😂

Like
Reply
Ahmed Agamy

Senior Software Engineer | Full Stack Engineer, Mean Stack Developer | AWS Community Builders

7y

والله انت برنس وشاطر فعلا

Like
Reply

To view or add a comment, sign in

More articles by Ahmed Adel Ismail

  • Sharing data across multiple Mobile Squads - with examples

    Earlier I shared an article suggesting a solution to a common problem with teams following the "Spotify Model", which…

  • SDD - Squad Driven Design

    Working in multiple big teams I've found that we are always trying to apply our known best practices in software, but…

    4 Comments
  • Easier Testing with MVVM, MVI, MVP and Kotlin Multiplatform

    Before we start, this article requires basic knowledge about the following topics : Clean Architecture Unit Testing…

    10 Comments
  • Android - A Cleaner Clean Architecture

    It has been a while now since Clean Architecture was out, and even many of us started embracing hexagonal (ports and…

    10 Comments
  • Beyond Functional Programming

    In the Android industry, lately functional programming was the all new stuff to learn, RxJava, Kotlin, and the whole…

    7 Comments
  • Dependency Injection in Clean Architecture

    After Google's Opinionated Guide to Dependency Injection Video, Google made a clear statement that they want developers…

    18 Comments
  • Meta Programming in Android

    Year after year we are getting rid of the boilerplate code that we need to write for small and simple tasks in Android,…

    2 Comments
  • MVI Pattern For Android In 4 Steps

    Lately I wrote an article about MVI pattern, but as we are facing new problems every day and face more use-cases, we…

    7 Comments
  • Agile - Moving Fast

    We always here about Agile, and think about which methodology do we use, what practices do we have, team velocity…

    1 Comment
  • Kotlin Unit Testing with Mockito

    I've always believed that, if the code is designed to be tested, we wont need any testing framework or library ..

    17 Comments

Insights from the community

Others also viewed

Explore topics