web-dev-qa-db-fra.com

Quelle est la différence entre Maybe et Optional de rxjava2?

Le doc dit 

Conceptuellement, c’est une union de Single et Completable fournissant le un moyen de capturer un motif d’émission où il pourrait y avoir 0 ou 1 élément ou une erreur signalée par une source réactive.

Mais je ne suis pas sûr de ce que cela signifie vraiment. Il semble que ce soit la Optional de Java8.

Les deux codes suivants ont le même résultat, mais je ne sais pas ce que Maybe peut faire et que Optional ne peut pas (ou ne peut pas être lourd).

  @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));
        }
      );
  }

Les résultats sont les mêmes :

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

Dans rxJava1, mon API permettait de renvoyer Observable<Optional<T>>, est-ce une mauvaise odeur? Devrais-je changer pour Observable<Maybe<T>>?

8
smallufo

Maybe est un wrapper autour d'une opération/événement qui peut avoir 

  1. Un seul résultat
  2. Pas de résultat
  3. Résultat d'erreur

Cependant, optionnel est un wrapper autour de value qui peut être soit

  1. Présent
  2. Absent 

Dans votre exemple, dans l'opération map, le calcul est synchrone (c'est-à-dire que 6/i est synchrone et peut entraîner une valeur immédiate) et que vous souhaitez propager une valeur (si la division est possible) ou une valeur vide (si la division n'est pas possible). Par conséquent, utiliser Optional a plus de sens. 

Il existe cependant d'autres options également:

  • Si vous voulez propager pourquoi la division n'est pas possible, vous voudrez signaler l'erreur qui s'est produite. Dans un tel cas, utiliser Maybe aura plus de sens. 
  • Si vous n'êtes pas intéressé à la fois par la valeur vide et par la raison de l'erreur, vous voulez simplement ignorer la propagation de ces résultats. Dans un tel scénario, j'utiliserais une flatMap au lieu de map. Je n'aurai alors plus besoin d'utiliser Optional ou Maybe

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

Maybe est également utile lorsque vous avez une Observable qui peut émettre plusieurs valeurs mais que vous ne souhaitez, par exemple, que la première, et que vous utilisez donc l'opérateur firstElement() sur l'observable. Cela renvoie un Maybe car il existe une seule valeur ou il n'y a pas de valeur (si la source Observable n'émet aucune valeur avant la fin) ou une erreur (si la source présente des erreurs observables avant d'émettre une valeur). 

17
Praveer Gupta

Maybe est un flux lazy de zéro ou un objet (et être un flux peut entraîner une erreur). Optional n'est pas paresseux, il est présent ou absent. Il n'y a pas de sens du calcul différé avec Optional alors qu'il y a avec Maybe.

9
Dave Moten

La différence par rapport à votre question est que Maybe peut propager une erreur alors que Optional ne le peut pas. Dans votre exemple, il est impossible de faire la distinction entre une erreur et un résultat vide. Si le traitement des erreurs est important, Optional est inutile, alors que Maybe a Maybe.error(Throwable). API, en ce qui concerne votre cas d'utilisation, je préférerais Single à Maybe - car il génère soit une erreur, soit un résultat unique, le type de résultat renvoyé serait donc Observable<Single<T>>

4
m.ostroverkhov

rxjava [2] cible Java6. Cela signifie qu'il n'y a pas de support Optional intégré, et ils doivent apporter le leur. Semblable à la façon dont ils doivent apporter leurs propres types Function.

Si votre application/bibliothèque ne supporte que Java> = 8, vous pouvez utiliser ce qui vous convient le mieux.

1
Matthias247