0
# Maybe Values
1
2
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).
3
4
## Capabilities
5
6
### Maybe Creation
7
8
Factory methods for creating Maybe instances.
9
10
```java { .api }
11
/**
12
* Creates a Maybe that emits the provided item then completes
13
*/
14
public static <T> Maybe<T> just(T item);
15
16
/**
17
* Creates an empty Maybe that only calls onComplete
18
*/
19
public static <T> Maybe<T> empty();
20
21
/**
22
* Creates a Maybe from a Callable that may return null
23
*/
24
public static <T> Maybe<T> fromCallable(Callable<? extends T> callable);
25
26
/**
27
* Creates a Maybe from an Action (completes empty when action finishes)
28
*/
29
public static <T> Maybe<T> fromAction(Action action);
30
31
/**
32
* Creates a Maybe from a Runnable (completes empty when runnable finishes)
33
*/
34
public static <T> Maybe<T> fromRunnable(Runnable runnable);
35
36
/**
37
* Creates a Maybe from a Future
38
*/
39
public static <T> Maybe<T> fromFuture(Future<? extends T> future);
40
41
/**
42
* Creates a Maybe using the provided MaybeOnSubscribe function
43
*/
44
public static <T> Maybe<T> create(MaybeOnSubscribe<T> source);
45
46
/**
47
* Creates a Maybe that only calls onError
48
*/
49
public static <T> Maybe<T> error(Throwable exception);
50
public static <T> Maybe<T> error(Callable<? extends Throwable> errorSupplier);
51
52
/**
53
* Creates a Maybe that never emits any items and never terminates
54
*/
55
public static <T> Maybe<T> never();
56
57
/**
58
* Defers Maybe creation until subscription
59
*/
60
public static <T> Maybe<T> defer(Callable<? extends MaybeSource<? extends T>> maybeSupplier);
61
62
/**
63
* Creates a Maybe from a Single
64
*/
65
public static <T> Maybe<T> fromSingle(SingleSource<T> singleSource);
66
67
/**
68
* Creates a Maybe from an ObservableSource that emits at most one item
69
*/
70
public static <T> Maybe<T> fromObservable(ObservableSource<T> observableSource);
71
```
72
73
### Transformation Operators
74
75
Transform the value emitted by a Maybe.
76
77
```java { .api }
78
/**
79
* Transforms the item using a function (if present)
80
*/
81
public final <R> Maybe<R> map(Function<? super T, ? extends R> mapper);
82
83
/**
84
* Transforms the item into another Maybe and flattens the result
85
*/
86
public final <R> Maybe<R> flatMap(Function<? super T, ? extends MaybeSource<? extends R>> mapper);
87
88
/**
89
* Transforms the item into an Observable
90
*/
91
public final <R> Observable<R> flatMapObservable(Function<? super T, ? extends ObservableSource<? extends R>> mapper);
92
93
/**
94
* Transforms the item into a Flowable
95
*/
96
public final <R> Flowable<R> flatMapFlowable(Function<? super T, ? extends Publisher<? extends R>> mapper);
97
98
/**
99
* Transforms the item into a Single
100
*/
101
public final <R> Single<R> flatMapSingle(Function<? super T, ? extends SingleSource<? extends R>> mapper);
102
103
/**
104
* Transforms the item into a Completable
105
*/
106
public final Completable flatMapCompletable(Function<? super T, ? extends CompletableSource> mapper);
107
108
/**
109
* Casts the item to the specified type
110
*/
111
public final <U> Maybe<U> cast(Class<U> clazz);
112
```
113
114
### Filtering and Conditional Operators
115
116
Apply conditions and filters to Maybe operations.
117
118
```java { .api }
119
/**
120
* Filters the item based on a predicate (converts success to empty if predicate fails)
121
*/
122
public final Maybe<T> filter(Predicate<? super T> predicate);
123
124
/**
125
* Returns a Maybe that emits a default item if this Maybe is empty
126
*/
127
public final Maybe<T> defaultIfEmpty(T defaultItem);
128
129
/**
130
* Returns a Single that emits a default item if this Maybe is empty
131
*/
132
public final Single<T> defaultIfEmpty(T defaultItem);
133
134
/**
135
* Switches to another Maybe if this Maybe is empty
136
*/
137
public final Maybe<T> switchIfEmpty(MaybeSource<? extends T> other);
138
139
/**
140
* Tests whether the Maybe is empty
141
*/
142
public final Single<Boolean> isEmpty();
143
144
/**
145
* Tests whether the Maybe emits the specified item
146
*/
147
public final Single<Boolean> contains(Object item);
148
```
149
150
### Error Handling
151
152
Handle errors in Maybe operations.
153
154
```java { .api }
155
/**
156
* Returns a Maybe that emits a specified item if the source emits an error
157
*/
158
public final Maybe<T> onErrorReturn(Function<? super Throwable, ? extends T> valueSupplier);
159
public final Maybe<T> onErrorReturn(T value);
160
161
/**
162
* Returns a Maybe that switches to another Maybe if the source emits an error
163
*/
164
public final Maybe<T> onErrorResumeNext(Function<? super Throwable, ? extends MaybeSource<? extends T>> resumeFunction);
165
public final Maybe<T> onErrorResumeNext(MaybeSource<? extends T> resumeMaybeSource);
166
167
/**
168
* Converts errors to empty completion
169
*/
170
public final Maybe<T> onErrorComplete();
171
public final Maybe<T> onErrorComplete(Predicate<? super Throwable> predicate);
172
173
/**
174
* Retry on error
175
*/
176
public final Maybe<T> retry();
177
public final Maybe<T> retry(long times);
178
public final Maybe<T> retry(BiPredicate<? super Integer, ? super Throwable> predicate);
179
public final Maybe<T> retryWhen(Function<? super Flowable<Throwable>, ? extends Publisher<?>> handler);
180
```
181
182
### Combining Maybes
183
184
Combine multiple Maybes.
185
186
```java { .api }
187
/**
188
* Combines two Maybes using a combiner function (only if both emit)
189
*/
190
public static <T1, T2, R> Maybe<R> zip(
191
MaybeSource<? extends T1> source1,
192
MaybeSource<? extends T2> source2,
193
BiFunction<? super T1, ? super T2, ? extends R> zipper
194
);
195
196
/**
197
* Zips up to 9 Maybes
198
*/
199
public static <T1, T2, T3, R> Maybe<R> zip(
200
MaybeSource<? extends T1> source1,
201
MaybeSource<? extends T2> source2,
202
MaybeSource<? extends T3> source3,
203
Function3<? super T1, ? super T2, ? super T3, ? extends R> zipper
204
);
205
206
/**
207
* Returns the first Maybe to emit or complete
208
*/
209
public static <T> Maybe<T> amb(MaybeSource<? extends T>... sources);
210
public static <T> Maybe<T> amb(Iterable<? extends MaybeSource<? extends T>> sources);
211
212
/**
213
* Concatenates Maybes sequentially into an Observable
214
*/
215
public static <T> Observable<T> concat(MaybeSource<? extends T>... sources);
216
public static <T> Observable<T> concat(Iterable<? extends MaybeSource<? extends T>> sources);
217
218
/**
219
* Merges Maybes into an Observable
220
*/
221
public static <T> Observable<T> merge(MaybeSource<? extends T>... sources);
222
public static <T> Observable<T> merge(Iterable<? extends MaybeSource<? extends T>> sources);
223
224
/**
225
* Concatenates this Maybe with another MaybeSource
226
*/
227
public final Observable<T> concatWith(MaybeSource<? extends T> other);
228
```
229
230
### Threading
231
232
Control execution context for Maybes.
233
234
```java { .api }
235
/**
236
* Specifies the Scheduler on which the Maybe will operate
237
*/
238
public final Maybe<T> subscribeOn(Scheduler scheduler);
239
240
/**
241
* Specifies the Scheduler on which observers will be notified
242
*/
243
public final Maybe<T> observeOn(Scheduler scheduler);
244
```
245
246
### Timing Operations
247
248
Add delays and timeouts to Maybes.
249
250
```java { .api }
251
/**
252
* Delays the emission of the success signal
253
*/
254
public final Maybe<T> delay(long time, TimeUnit unit);
255
public final Maybe<T> delay(long time, TimeUnit unit, Scheduler scheduler);
256
257
/**
258
* Adds a timeout to the Maybe
259
*/
260
public final Maybe<T> timeout(long timeout, TimeUnit timeUnit);
261
public final Maybe<T> timeout(long timeout, TimeUnit timeUnit, Scheduler scheduler);
262
public final Maybe<T> timeout(long timeout, TimeUnit timeUnit, MaybeSource<? extends T> other);
263
```
264
265
### Conversion Operations
266
267
Convert Maybe to other reactive types.
268
269
```java { .api }
270
/**
271
* Converts Maybe to Observable
272
*/
273
public final Observable<T> toObservable();
274
275
/**
276
* Converts Maybe to Flowable
277
*/
278
public final Flowable<T> toFlowable();
279
280
/**
281
* Converts Maybe to Single (throws NoSuchElementException if empty)
282
*/
283
public final Single<T> toSingle();
284
285
/**
286
* Converts Maybe to Single with default value if empty
287
*/
288
public final Single<T> toSingle(T defaultValue);
289
290
/**
291
* Converts Maybe to Completable (ignoring any value)
292
*/
293
public final Completable toCompletable();
294
```
295
296
### Subscription and Consumption
297
298
Subscribe to a Maybe and consume the emitted value.
299
300
```java { .api }
301
/**
302
* Subscribes with separate callbacks
303
*/
304
public final Disposable subscribe();
305
public final Disposable subscribe(Consumer<? super T> onSuccess);
306
public final Disposable subscribe(Consumer<? super T> onSuccess, Consumer<? super Throwable> onError);
307
public final Disposable subscribe(Consumer<? super T> onSuccess, Consumer<? super Throwable> onError, Action onComplete);
308
309
/**
310
* Subscribes with a MaybeObserver
311
*/
312
public final void subscribe(MaybeObserver<? super T> observer);
313
314
/**
315
* Blocking operations - use with caution
316
*/
317
public final T blockingGet();
318
public final T blockingGet(T defaultValue);
319
```
320
321
### Utility Operations
322
323
Additional utility operations for Maybes.
324
325
```java { .api }
326
/**
327
* Caches the result of the Maybe
328
*/
329
public final Maybe<T> cache();
330
331
/**
332
* Performs side-effects without affecting the Maybe
333
*/
334
public final Maybe<T> doOnSuccess(Consumer<? super T> onSuccess);
335
public final Maybe<T> doOnError(Consumer<? super Throwable> onError);
336
public final Maybe<T> doOnComplete(Action onComplete);
337
public final Maybe<T> doOnSubscribe(Consumer<? super Disposable> onSubscribe);
338
public final Maybe<T> doOnDispose(Action onDispose);
339
public final Maybe<T> doFinally(Action onFinally);
340
341
/**
342
* Repeats the Maybe subscription
343
*/
344
public final Observable<T> repeat();
345
public final Observable<T> repeat(long times);
346
```
347
348
## Usage Examples
349
350
**Basic Maybe Creation and Subscription:**
351
352
```java
353
import io.reactivex.Maybe;
354
import io.reactivex.MaybeObserver;
355
import io.reactivex.disposables.Disposable;
356
357
// Maybe with value
358
Maybe<String> withValue = Maybe.just("Hello Maybe");
359
360
// Empty Maybe
361
Maybe<String> empty = Maybe.empty();
362
363
// Subscribe to Maybe with value
364
withValue.subscribe(new MaybeObserver<String>() {
365
@Override
366
public void onSubscribe(Disposable d) {
367
System.out.println("Subscribed");
368
}
369
370
@Override
371
public void onSuccess(String value) {
372
System.out.println("Success: " + value);
373
}
374
375
@Override
376
public void onError(Throwable e) {
377
System.err.println("Error: " + e.getMessage());
378
}
379
380
@Override
381
public void onComplete() {
382
System.out.println("Completed empty");
383
}
384
});
385
386
// Lambda-style subscription
387
empty.subscribe(
388
value -> System.out.println("Got: " + value),
389
error -> error.printStackTrace(),
390
() -> System.out.println("Empty completed")
391
);
392
```
393
394
**Maybe from Nullable Operations:**
395
396
```java
397
// Database lookup that may return null
398
Maybe<User> findUser(int userId) {
399
return Maybe.fromCallable(() -> {
400
// Simulate database lookup
401
if (userId == 1) {
402
return new User("John Doe");
403
}
404
return null; // This will result in empty Maybe
405
}).subscribeOn(Schedulers.io());
406
}
407
408
findUser(1).subscribe(
409
user -> System.out.println("Found user: " + user.getName()),
410
error -> error.printStackTrace(),
411
() -> System.out.println("User not found")
412
);
413
```
414
415
**Conditional Operations with Maybe:**
416
417
```java
418
Maybe<Integer> source = Maybe.just(5);
419
420
// Filter converts success to empty if predicate fails
421
source.filter(x -> x > 10)
422
.subscribe(
423
value -> System.out.println("Large number: " + value),
424
error -> error.printStackTrace(),
425
() -> System.out.println("Number too small")
426
);
427
428
// Provide default for empty
429
source.filter(x -> x > 10)
430
.defaultIfEmpty(-1)
431
.subscribe(value -> System.out.println("Result: " + value));
432
433
// Switch to alternative if empty
434
source.filter(x -> x > 10)
435
.switchIfEmpty(Maybe.just(0))
436
.subscribe(value -> System.out.println("Result: " + value));
437
```
438
439
**Chaining Maybe Operations:**
440
441
```java
442
Maybe<String> username = Maybe.just("john");
443
444
// Chain operations
445
username
446
.map(name -> name.toUpperCase())
447
.filter(name -> name.length() > 3)
448
.flatMap(name -> Maybe.just("Hello, " + name))
449
.subscribe(
450
greeting -> System.out.println(greeting),
451
error -> error.printStackTrace(),
452
() -> System.out.println("No greeting generated")
453
);
454
```
455
456
**Converting Between Reactive Types:**
457
458
```java
459
Maybe<Integer> maybe = Maybe.just(42);
460
461
// Convert to Single (with default for empty case)
462
Single<Integer> single = maybe.toSingle(-1);
463
464
// Convert to Observable
465
Observable<Integer> observable = maybe.toObservable();
466
467
// Convert to Completable (ignoring value)
468
Completable completable = maybe.toCompletable();
469
470
// From other types
471
Single<String> singleSource = Single.just("Hello");
472
Maybe<String> fromSingle = singleSource.toMaybe();
473
474
Observable<String> observableSource = Observable.just("World");
475
Maybe<String> fromObservable = observableSource.firstElement();
476
```
477
478
**Error Handling with Maybe:**
479
480
```java
481
Maybe<String> riskyOperation = Maybe.fromCallable(() -> {
482
if (Math.random() > 0.7) {
483
throw new RuntimeException("Random failure");
484
}
485
if (Math.random() > 0.4) {
486
return "Success";
487
}
488
return null; // Empty
489
});
490
491
// Handle errors by converting to empty
492
riskyOperation
493
.onErrorComplete()
494
.subscribe(
495
value -> System.out.println("Success: " + value),
496
error -> error.printStackTrace(), // Won't be called
497
() -> System.out.println("Empty or error converted to empty")
498
);
499
500
// Handle errors with fallback value
501
riskyOperation
502
.onErrorReturn("Error fallback")
503
.subscribe(value -> System.out.println("Result: " + value));
504
```
505
506
**Combining Maybes:**
507
508
```java
509
Maybe<String> firstName = Maybe.just("John");
510
Maybe<String> lastName = Maybe.just("Doe");
511
512
// Zip only if both emit values
513
Maybe<String> fullName = Maybe.zip(firstName, lastName,
514
(first, last) -> first + " " + last);
515
516
fullName.subscribe(
517
name -> System.out.println("Full name: " + name),
518
error -> error.printStackTrace(),
519
() -> System.out.println("Incomplete name data")
520
);
521
522
// Amb - first to emit or complete wins
523
Maybe<String> fast = Maybe.just("Fast").delay(100, TimeUnit.MILLISECONDS);
524
Maybe<String> slow = Maybe.just("Slow").delay(200, TimeUnit.MILLISECONDS);
525
526
Maybe.amb(Arrays.asList(fast, slow))
527
.subscribe(result -> System.out.println("Winner: " + result));
528
```
529
530
## Types
531
532
```java { .api }
533
/**
534
* Observer interface for Maybes
535
*/
536
public interface MaybeObserver<T> {
537
void onSubscribe(Disposable d);
538
void onSuccess(T t);
539
void onError(Throwable e);
540
void onComplete();
541
}
542
543
/**
544
* Functional interface for creating Maybes
545
*/
546
public interface MaybeOnSubscribe<T> {
547
void subscribe(MaybeEmitter<T> emitter) throws Exception;
548
}
549
550
/**
551
* Emitter for MaybeOnSubscribe
552
*/
553
public interface MaybeEmitter<T> {
554
void onSuccess(T t);
555
void onError(Throwable t);
556
void onComplete();
557
void setDisposable(Disposable d);
558
void setCancellable(Cancellable c);
559
boolean isDisposed();
560
}
561
562
/**
563
* Base interface for Maybe sources
564
*/
565
public interface MaybeSource<T> {
566
void subscribe(MaybeObserver<? super T> observer);
567
}
568
```