Java.Reactive.What is reactive programming and how is it different from procedural programming?

Reactive Programming is a programming paradigm focused on asynchronous data streams and the propagation of change. It’s all about reacting to data as it comes in — like events, user interactions, or data updates — and building systems that respond to these changes automatically and efficiently.

🔹 Core Concepts:

  • Observables / Streams: Sequences of data/events over time.
  • Observers / Subscribers: React to new data or changes.
  • Operators: Transform, combine, filter, or debounce data streams.
  • Backpressure: Handle data flow control when consumers are slower than producers.

✅ Example Use Cases:

  • UI updates based on user input (e.g., search-as-you-type).
  • Real-time systems (chat apps, financial tickers).
  • Event-driven microservices.

🛠 Common Libraries:

  • RxJava (Java)
  • Reactor (Spring ecosystem)
  • RxJS (JavaScript)
  • Combine (Swift)

🔃 What is Procedural Programming?

Procedural Programming is a programming paradigm based on a sequence of steps or procedures (functions). It focuses on how to achieve a task through a linear series of commands and logic blocks.

🔹 Core Concepts:

  • Functions (procedures) and structured flow (if, loops, etc.)
  • Top-down approach: execute code step by step.
  • Mutation of variables and explicit state management.

✅ Example Use Cases:

  • Scripting tasks
  • Batch processing
  • System-level programming (e.g., C-based applications)

🛠 Common Languages:

  • C
  • Pascal
  • Early Java without reactive extensions

🔍 Key Differences at a Glance:

AspectReactive ProgrammingProcedural Programming
FocusAsynchronous data flow and event reactionStep-by-step task execution
Data FlowPush-based, streams of dataPull-based, function calls and returns
Control FlowEvent-driven, declarativeLinear, imperative
ConcurrencyBuilt-in (e.g., RxJava handles async by default)Manual (e.g., threads, futures)
State HandlingImmutable, state flows through streamsOften mutable, state changes explicitly
ExamplesAuto-complete search, real-time updatesCalculator logic, file processing scripts

🧠 Analogy:

  • Procedural is like a recipe: do step 1, then step 2, and so on.
  • Reactive is like a chef cooking while listening to multiple timers and ingredients arriving — constantly adapting based on inputs.

Example

🧪 Scenario:

You have a list of integers. You want to:

  1. Filter even numbers.
  2. Double them.
  3. Print each result.

🔧 Procedural Style (Plain Java)

import java.util.Arrays;
import java.util.List;

public class ProceduralExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

        for (Integer number : numbers) {
            if (number % 2 == 0) {
                int doubled = number * 2;
                System.out.println(doubled);
            }
        }
    }
}

✅ Characteristics:

  • Step-by-step logic.
  • Loops and conditions used explicitly.
  • Synchronous processing.

⚡️ Reactive Style (RxJava)

import io.reactivex.rxjava3.core.Observable;

public class ReactiveExample {
    public static void main(String[] args) {
        Observable<Integer> numbers = Observable.just(1, 2, 3, 4, 5, 6);

        numbers
            .filter(n -> n % 2 == 0)
            .map(n -> n * 2)
            .subscribe(System.out::println);
    }
}

✅ Characteristics:

  • Stream of data using Observable.
  • Declarative chaining of operations: filter, then map, then subscribe.
  • Asynchronous and reactive by nature (though this example runs synchronously for simplicity).
  • You don’t control the loop — RxJava handles data flow.

🧠 Extra Thoughts:

  • In real-world RxJava, you often deal with data from a database, network, or UI events, and not just static lists.
  • RxJava makes it easy to handle errors, retry, debounce, throttle, and combine streams — which is much harder with plain Java.

🧪 1. Debounced Search Input (like “search-as-you-type”)

Imagine a user types in a search box, and we want to:

  • Wait until the user pauses (e.g. 300ms).
  • Only then trigger a search request.
  • Cancel previous search if new input comes in.
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.schedulers.Schedulers;

import java.util.concurrent.TimeUnit;

public class DebouncedSearch {
    public static void main(String[] args) throws InterruptedException {
        Observable<String> userTyping = Observable
            .just("S", "St", "Sta", "Stan", "Stanl", "Stanley")
            .concatMap(s -> Observable.just(s).delay(100, TimeUnit.MILLISECONDS));

        userTyping
            .debounce(300, TimeUnit.MILLISECONDS)
            .observeOn(Schedulers.io())
            .subscribe(searchTerm -> System.out.println("Searching for: " + searchTerm));

        Thread.sleep(2000); // keep main thread alive
    }
}

✅ Result:

Only "Stanley" is printed after the user finishes typing.

This entry was posted in Без рубрики. Bookmark the permalink.