12

The doc says

Conceptually, it is a union of Single and Completable providing the means to capture an emission pattern where there could be 0 or 1 item or an error signalled by some reactive source.

But I am not sure what it truly means. It seems it is java8's Optional.

The following two codes have the same result , but I don't know what Maybe can do and Optional cannot (or cumbersome) do.

  @Test
  public void testMaybe1() {
    Observable.just(3, 2, 1, 0, -1)
      .map(i -> {
        try {
          int result = 6 / i;
          return Maybe.just(result);
        } catch (Exception e) {
          return Maybe.empty();
        }
      })
      .blockingForEach(maybe -> {
          logger.info("result = {}", maybe.blockingGet());
        }
      );
  }


  @Test
  public void testMaybe2() {
    Observable.just(3, 2, 1, 0, -1)
      .map(i -> {
        try {
          int result = 6 / i;
          return Optional.of(result);
        } catch (Exception e) {
          return Optional.empty();
        }
      })
      .blockingForEach(opt -> {
          logger.info("result = {}", opt.orElse(null));
        }
      );
  }

The results are the same :

result = 2
result = 3
result = 6
result = null
result = -6

In rxJava1 , My API used to return Observable<Optional<T>> , Is it a bad smell ? Should I change to Observable<Maybe<T>> ?

4

4 回答 4

27

Maybe is a wrapper around an operation/event that may have either

  1. A single result
  2. No result
  3. Error result

However Optional is a wrapper around a value that may either be

  1. Present
  2. Absent

In your example, in the map operation, the computation is synchronous (i.e. 6/i is synchronous and can result in a value immediately) and you want to propagate a value (if division is possible) or empty value (if division is not possible). Hence using Optional makes more sense.

There are however other options also:

  • If you want to propagate why division is not possible then you would want to report the exception that occurred. In such a case using Maybe will make more sense.
  • If you are not interested in both empty value and reason of error, then you simply want to skip propagating those results. In such a scenario I would use a flatMap instead of map. I will then not have to use any of Optional or Maybe.

    .flatMap(i -> { 
      try { 
        int result = 6 / i; 
        return Observable.just(result); 
      } catch (Exception e) { 
        return Observable.empty(); 
      } 
    }) 
    

Maybe is also useful when you have an Observable that can emit multiple values but you are interested in, let's say, only the first one and hence you use the firstElement() operator on the Observable. This returns a Maybe because either there is a single value, or there is no value (if source Observable does not emit any value before completing) or there is an error (if source Observable errors before emitting any value).

于 2016-11-05T21:01:25.310 回答
11

Maybe is a lazy stream of zero or one things (and being a stream can result in an error). Optional is not lazy, it it is either present or absent. There is no sense of deferred calculation with an Optional whereas there is with Maybe.

于 2016-11-07T03:38:24.627 回答
6

The difference relevant to your question is that Maybe can propagate error while Optional cannot - in your example one cannot distinguish between error and empty result. If error handling is important, Optional is useless, while Maybe has Maybe.error(Throwable). API-wise, for your use case I would prefer Single to Maybe - because it yields either Error or single Result, so return type would be Observable<Single<T>>

于 2016-11-05T16:36:16.287 回答
2

RxJava 2 targets Java 6. This means there is no builtin Optional support guaranteed, and they have to bring their own. Similar to how they have to bring their own Function types.

If your application/library only supports Java >= 8 you can use whatever suits you better.

于 2016-11-05T15:05:51.873 回答