RxJava: Reactive Extensions for the JVM – a library for composing asynchronous and event-based programs using observable sequences for the Java VM.
—
Reactive type that emits 0 or 1 item or an error. Maybe is useful for operations that may or may not return a value, bridging the gap between Single (always 1 item) and Observable (0-N items).
Factory methods for creating Maybe instances.
/**
* Creates a Maybe that emits the provided item then completes
*/
public static <T> Maybe<T> just(T item);
/**
* Creates an empty Maybe that only calls onComplete
*/
public static <T> Maybe<T> empty();
/**
* Creates a Maybe from a Callable that may return null
*/
public static <T> Maybe<T> fromCallable(Callable<? extends T> callable);
/**
* Creates a Maybe from an Action (completes empty when action finishes)
*/
public static <T> Maybe<T> fromAction(Action action);
/**
* Creates a Maybe from a Runnable (completes empty when runnable finishes)
*/
public static <T> Maybe<T> fromRunnable(Runnable runnable);
/**
* Creates a Maybe from a Future
*/
public static <T> Maybe<T> fromFuture(Future<? extends T> future);
/**
* Creates a Maybe using the provided MaybeOnSubscribe function
*/
public static <T> Maybe<T> create(MaybeOnSubscribe<T> source);
/**
* Creates a Maybe that only calls onError
*/
public static <T> Maybe<T> error(Throwable exception);
public static <T> Maybe<T> error(Callable<? extends Throwable> errorSupplier);
/**
* Creates a Maybe that never emits any items and never terminates
*/
public static <T> Maybe<T> never();
/**
* Defers Maybe creation until subscription
*/
public static <T> Maybe<T> defer(Callable<? extends MaybeSource<? extends T>> maybeSupplier);
/**
* Creates a Maybe from a Single
*/
public static <T> Maybe<T> fromSingle(SingleSource<T> singleSource);
/**
* Creates a Maybe from an ObservableSource that emits at most one item
*/
public static <T> Maybe<T> fromObservable(ObservableSource<T> observableSource);Transform the value emitted by a Maybe.
/**
* Transforms the item using a function (if present)
*/
public final <R> Maybe<R> map(Function<? super T, ? extends R> mapper);
/**
* Transforms the item into another Maybe and flattens the result
*/
public final <R> Maybe<R> flatMap(Function<? super T, ? extends MaybeSource<? extends R>> mapper);
/**
* Transforms the item into an Observable
*/
public final <R> Observable<R> flatMapObservable(Function<? super T, ? extends ObservableSource<? extends R>> mapper);
/**
* Transforms the item into a Flowable
*/
public final <R> Flowable<R> flatMapFlowable(Function<? super T, ? extends Publisher<? extends R>> mapper);
/**
* Transforms the item into a Single
*/
public final <R> Single<R> flatMapSingle(Function<? super T, ? extends SingleSource<? extends R>> mapper);
/**
* Transforms the item into a Completable
*/
public final Completable flatMapCompletable(Function<? super T, ? extends CompletableSource> mapper);
/**
* Casts the item to the specified type
*/
public final <U> Maybe<U> cast(Class<U> clazz);Apply conditions and filters to Maybe operations.
/**
* Filters the item based on a predicate (converts success to empty if predicate fails)
*/
public final Maybe<T> filter(Predicate<? super T> predicate);
/**
* Returns a Maybe that emits a default item if this Maybe is empty
*/
public final Maybe<T> defaultIfEmpty(T defaultItem);
/**
* Returns a Single that emits a default item if this Maybe is empty
*/
public final Single<T> defaultIfEmpty(T defaultItem);
/**
* Switches to another Maybe if this Maybe is empty
*/
public final Maybe<T> switchIfEmpty(MaybeSource<? extends T> other);
/**
* Tests whether the Maybe is empty
*/
public final Single<Boolean> isEmpty();
/**
* Tests whether the Maybe emits the specified item
*/
public final Single<Boolean> contains(Object item);Handle errors in Maybe operations.
/**
* Returns a Maybe that emits a specified item if the source emits an error
*/
public final Maybe<T> onErrorReturn(Function<? super Throwable, ? extends T> valueSupplier);
public final Maybe<T> onErrorReturn(T value);
/**
* Returns a Maybe that switches to another Maybe if the source emits an error
*/
public final Maybe<T> onErrorResumeNext(Function<? super Throwable, ? extends MaybeSource<? extends T>> resumeFunction);
public final Maybe<T> onErrorResumeNext(MaybeSource<? extends T> resumeMaybeSource);
/**
* Converts errors to empty completion
*/
public final Maybe<T> onErrorComplete();
public final Maybe<T> onErrorComplete(Predicate<? super Throwable> predicate);
/**
* Retry on error
*/
public final Maybe<T> retry();
public final Maybe<T> retry(long times);
public final Maybe<T> retry(BiPredicate<? super Integer, ? super Throwable> predicate);
public final Maybe<T> retryWhen(Function<? super Flowable<Throwable>, ? extends Publisher<?>> handler);Combine multiple Maybes.
/**
* Combines two Maybes using a combiner function (only if both emit)
*/
public static <T1, T2, R> Maybe<R> zip(
MaybeSource<? extends T1> source1,
MaybeSource<? extends T2> source2,
BiFunction<? super T1, ? super T2, ? extends R> zipper
);
/**
* Zips up to 9 Maybes
*/
public static <T1, T2, T3, R> Maybe<R> zip(
MaybeSource<? extends T1> source1,
MaybeSource<? extends T2> source2,
MaybeSource<? extends T3> source3,
Function3<? super T1, ? super T2, ? super T3, ? extends R> zipper
);
/**
* Returns the first Maybe to emit or complete
*/
public static <T> Maybe<T> amb(MaybeSource<? extends T>... sources);
public static <T> Maybe<T> amb(Iterable<? extends MaybeSource<? extends T>> sources);
/**
* Concatenates Maybes sequentially into an Observable
*/
public static <T> Observable<T> concat(MaybeSource<? extends T>... sources);
public static <T> Observable<T> concat(Iterable<? extends MaybeSource<? extends T>> sources);
/**
* Merges Maybes into an Observable
*/
public static <T> Observable<T> merge(MaybeSource<? extends T>... sources);
public static <T> Observable<T> merge(Iterable<? extends MaybeSource<? extends T>> sources);
/**
* Concatenates this Maybe with another MaybeSource
*/
public final Observable<T> concatWith(MaybeSource<? extends T> other);Control execution context for Maybes.
/**
* Specifies the Scheduler on which the Maybe will operate
*/
public final Maybe<T> subscribeOn(Scheduler scheduler);
/**
* Specifies the Scheduler on which observers will be notified
*/
public final Maybe<T> observeOn(Scheduler scheduler);Add delays and timeouts to Maybes.
/**
* Delays the emission of the success signal
*/
public final Maybe<T> delay(long time, TimeUnit unit);
public final Maybe<T> delay(long time, TimeUnit unit, Scheduler scheduler);
/**
* Adds a timeout to the Maybe
*/
public final Maybe<T> timeout(long timeout, TimeUnit timeUnit);
public final Maybe<T> timeout(long timeout, TimeUnit timeUnit, Scheduler scheduler);
public final Maybe<T> timeout(long timeout, TimeUnit timeUnit, MaybeSource<? extends T> other);Convert Maybe to other reactive types.
/**
* Converts Maybe to Observable
*/
public final Observable<T> toObservable();
/**
* Converts Maybe to Flowable
*/
public final Flowable<T> toFlowable();
/**
* Converts Maybe to Single (throws NoSuchElementException if empty)
*/
public final Single<T> toSingle();
/**
* Converts Maybe to Single with default value if empty
*/
public final Single<T> toSingle(T defaultValue);
/**
* Converts Maybe to Completable (ignoring any value)
*/
public final Completable toCompletable();Subscribe to a Maybe and consume the emitted value.
/**
* Subscribes with separate callbacks
*/
public final Disposable subscribe();
public final Disposable subscribe(Consumer<? super T> onSuccess);
public final Disposable subscribe(Consumer<? super T> onSuccess, Consumer<? super Throwable> onError);
public final Disposable subscribe(Consumer<? super T> onSuccess, Consumer<? super Throwable> onError, Action onComplete);
/**
* Subscribes with a MaybeObserver
*/
public final void subscribe(MaybeObserver<? super T> observer);
/**
* Blocking operations - use with caution
*/
public final T blockingGet();
public final T blockingGet(T defaultValue);Additional utility operations for Maybes.
/**
* Caches the result of the Maybe
*/
public final Maybe<T> cache();
/**
* Performs side-effects without affecting the Maybe
*/
public final Maybe<T> doOnSuccess(Consumer<? super T> onSuccess);
public final Maybe<T> doOnError(Consumer<? super Throwable> onError);
public final Maybe<T> doOnComplete(Action onComplete);
public final Maybe<T> doOnSubscribe(Consumer<? super Disposable> onSubscribe);
public final Maybe<T> doOnDispose(Action onDispose);
public final Maybe<T> doFinally(Action onFinally);
/**
* Repeats the Maybe subscription
*/
public final Observable<T> repeat();
public final Observable<T> repeat(long times);Basic Maybe Creation and Subscription:
import io.reactivex.Maybe;
import io.reactivex.MaybeObserver;
import io.reactivex.disposables.Disposable;
// Maybe with value
Maybe<String> withValue = Maybe.just("Hello Maybe");
// Empty Maybe
Maybe<String> empty = Maybe.empty();
// Subscribe to Maybe with value
withValue.subscribe(new MaybeObserver<String>() {
@Override
public void onSubscribe(Disposable d) {
System.out.println("Subscribed");
}
@Override
public void onSuccess(String value) {
System.out.println("Success: " + value);
}
@Override
public void onError(Throwable e) {
System.err.println("Error: " + e.getMessage());
}
@Override
public void onComplete() {
System.out.println("Completed empty");
}
});
// Lambda-style subscription
empty.subscribe(
value -> System.out.println("Got: " + value),
error -> error.printStackTrace(),
() -> System.out.println("Empty completed")
);Maybe from Nullable Operations:
// Database lookup that may return null
Maybe<User> findUser(int userId) {
return Maybe.fromCallable(() -> {
// Simulate database lookup
if (userId == 1) {
return new User("John Doe");
}
return null; // This will result in empty Maybe
}).subscribeOn(Schedulers.io());
}
findUser(1).subscribe(
user -> System.out.println("Found user: " + user.getName()),
error -> error.printStackTrace(),
() -> System.out.println("User not found")
);Conditional Operations with Maybe:
Maybe<Integer> source = Maybe.just(5);
// Filter converts success to empty if predicate fails
source.filter(x -> x > 10)
.subscribe(
value -> System.out.println("Large number: " + value),
error -> error.printStackTrace(),
() -> System.out.println("Number too small")
);
// Provide default for empty
source.filter(x -> x > 10)
.defaultIfEmpty(-1)
.subscribe(value -> System.out.println("Result: " + value));
// Switch to alternative if empty
source.filter(x -> x > 10)
.switchIfEmpty(Maybe.just(0))
.subscribe(value -> System.out.println("Result: " + value));Chaining Maybe Operations:
Maybe<String> username = Maybe.just("john");
// Chain operations
username
.map(name -> name.toUpperCase())
.filter(name -> name.length() > 3)
.flatMap(name -> Maybe.just("Hello, " + name))
.subscribe(
greeting -> System.out.println(greeting),
error -> error.printStackTrace(),
() -> System.out.println("No greeting generated")
);Converting Between Reactive Types:
Maybe<Integer> maybe = Maybe.just(42);
// Convert to Single (with default for empty case)
Single<Integer> single = maybe.toSingle(-1);
// Convert to Observable
Observable<Integer> observable = maybe.toObservable();
// Convert to Completable (ignoring value)
Completable completable = maybe.toCompletable();
// From other types
Single<String> singleSource = Single.just("Hello");
Maybe<String> fromSingle = singleSource.toMaybe();
Observable<String> observableSource = Observable.just("World");
Maybe<String> fromObservable = observableSource.firstElement();Error Handling with Maybe:
Maybe<String> riskyOperation = Maybe.fromCallable(() -> {
if (Math.random() > 0.7) {
throw new RuntimeException("Random failure");
}
if (Math.random() > 0.4) {
return "Success";
}
return null; // Empty
});
// Handle errors by converting to empty
riskyOperation
.onErrorComplete()
.subscribe(
value -> System.out.println("Success: " + value),
error -> error.printStackTrace(), // Won't be called
() -> System.out.println("Empty or error converted to empty")
);
// Handle errors with fallback value
riskyOperation
.onErrorReturn("Error fallback")
.subscribe(value -> System.out.println("Result: " + value));Combining Maybes:
Maybe<String> firstName = Maybe.just("John");
Maybe<String> lastName = Maybe.just("Doe");
// Zip only if both emit values
Maybe<String> fullName = Maybe.zip(firstName, lastName,
(first, last) -> first + " " + last);
fullName.subscribe(
name -> System.out.println("Full name: " + name),
error -> error.printStackTrace(),
() -> System.out.println("Incomplete name data")
);
// Amb - first to emit or complete wins
Maybe<String> fast = Maybe.just("Fast").delay(100, TimeUnit.MILLISECONDS);
Maybe<String> slow = Maybe.just("Slow").delay(200, TimeUnit.MILLISECONDS);
Maybe.amb(Arrays.asList(fast, slow))
.subscribe(result -> System.out.println("Winner: " + result));/**
* Observer interface for Maybes
*/
public interface MaybeObserver<T> {
void onSubscribe(Disposable d);
void onSuccess(T t);
void onError(Throwable e);
void onComplete();
}
/**
* Functional interface for creating Maybes
*/
public interface MaybeOnSubscribe<T> {
void subscribe(MaybeEmitter<T> emitter) throws Exception;
}
/**
* Emitter for MaybeOnSubscribe
*/
public interface MaybeEmitter<T> {
void onSuccess(T t);
void onError(Throwable t);
void onComplete();
void setDisposable(Disposable d);
void setCancellable(Cancellable c);
boolean isDisposed();
}
/**
* Base interface for Maybe sources
*/
public interface MaybeSource<T> {
void subscribe(MaybeObserver<? super T> observer);
}Install with Tessl CLI
npx tessl i tessl/maven-io-reactivex-rxjava2--rxjava