In questo quarto post dedicato al framework RxJava descriveremo gli operatori della famiglia dei Conditional and Boolean Operators, ovvero di quegli operatori che operano sugli Observable
o sugli item da essi emessi.
Conditional and Boolean Operators
All
L’operatore All determina se tutti gli item emessi da un Observable
soddisfano un determinato criterio di input. L’operatore riceve quindi come parametro una funzione applicabile agli elementi emessi dall’Observable
e che restituisce in output un valore booleano. All restituisce un Observable
che emette un singolo valore booleano:
TRUE
se e solo se la sorgente osservabile termina normalmente e tutti gli elementi da lei emessi sono valutati comeTRUE
dalla funzione di input;FALSE
se un qualsiasi elemento emesso dalla sorgente osservabile viene valutato comeFALSE
dalla funzione di input.
Ad esempio, il seguente codice restituisce false
in quanto tra gli elementi emessi il 6
risulta maggiore di 5
. Eliminando tale elemente l’output restituito sarà true
.
1 2 3 |
Observable.just(1, 2, 3, 4, 5, 6) .all( x -> x <= 5 ) .subscribe( System.out::println ); |
Amb
Dati due o più Observable
sorgenti, l’operatore Amb emette tutti e soli gli elementi emessi dalla sorgente che emette un qualsiasi tipo di segnale per primo (onError
, onNext
, onComplete
). Tutti gli item emessi dalle altre sorgenti saranno completamente ignorati. In RxJava esistono due implementazioni dell’operatore: amb()
che riceve in input un oggetto Iterable
(es. List
) di Observable
, mostrato nel codice seguente, ed ambWith()
che invece accetta un Array
.
1 2 3 4 5 6 7 8 |
List<Observable<Long>> sources = new ArrayList<Observable<Long>>(); sources.add( Observable.interval( 1, TimeUnit.SECONDS ) ); sources.add( Observable.timer( 2, TimeUnit.SECONDS ) ); Observable .amb(sources) .subscribe( System.out::println ); |
Contains e IsEmpty
L’operatore Contains determina se un determinato item viene emesso dall’Observable
sorgente. L’Observable
risultante emette quindi il valore booleano TRUE
nel caso in cui l’item sia emesso oppure FALSE
nel caso in cui l’Observable
sorgente termini senza emettere l’item. Consideriamo ad esempio i due casi mostrati di seguito: il primo restituirà TRUE
dopo 5
secondi dall’avvio dell’applicazione, esattamente quando l’operatore interval()
emetterà il valore 5
. Il secondo, invece, restituirà immediatamente FALSE
.
1 2 3 4 5 6 7 |
Observable.interval( 1, TimeUnit.SECONDS ) .contains( 5L ) .subscribe( System.out::println ); Observable.just( 1, 2, 3, 4 ) .contains( 5L ) .subscribe( System.out::println ); |
TRUE
se l’Observable
sorgente termina senza emettere alcun elemento e FALSE
in caso contrario.
1 2 3 |
Observable.just( 1, 2, 3, 4 ) .isEmpty() .subscribe( System.out::println ); |
DefaultIfEmpty e SwitchIfEmpty
L’operatore DefaultIfEmpty replica esattamente gli elementi emessi dall’Observable
di origine. Se però tale sorgente termina normalmente (con un onComplete
) senza emettere alcun elemento, allora l’Osservable
restituito dall’operatore DefaultIfEmpty emetterà un unico elemento, che è quello definito in input all’operatore stesso, prima di terminare anch’esso. Si consideri il seguente codice di esempio:
1 2 3 4 5 6 7 |
Observable.empty() .defaultIfEmpty( "Empty" ) .subscribe( val -> System.out.println("next: " + val), err -> System.err.println(err) , () -> System.out.println("completed") ); |
1 2 |
next: Empty completed |
Un operatore analogo SwitchIfEmpty che, invece di emettere un valore di backup se la sorgente di origine termina senza aver emesso alcun item, emette gli elementi recuperati da un Observable
di backup. Il seguente codice, ad esempio:
1 2 3 4 5 6 7 |
Observable.empty() .switchIfEmpty( Observable.just("A", "B", "C" ) ) .subscribe( val -> System.out.println("next: " + val), err -> System.err.println(err), () -> System.out.println("completed") ); |
1 2 3 4 |
next: A next: B next: C completed |
SequenceEqual
L’operatore SequenceEqual riceve in input due Observable
e confronta gli elementi emessi da ciascun di essi, restituendo un Observable
che emetterà un solo boolean
:
TRUE
solo se entrambe le sequenze emesse dagliObservable
sono uguali, ovvero sono gli stessi elementi, nello stesso ordine, con lo stesso stato di terminazione.FALSE
altrimenti.
Ad esempio il seguente codice:
1 2 3 4 |
Observable.sequenceEqual( Observable.just( "A", "B", "C" ), Observable.just( "A", "C", "C" ) ) .subscribe( System.out::println ); |
restituisce FALSE
in quanto le due sequenze sono differenti. Esiste una variante dell’operatore che riceve in input come ulteriore parametro una funzione che è utilizzata per eseguire il confronto tra gli item emessi. Confronto che ovviamente è eseguito nell’ordine di emissione. Modifichiamo ad esempio il codice procedente nel seguente modo:
1 2 3 4 5 |
Observable.sequenceEqual( Observable.just( "A", "B", "C" ), Observable.just( "A", "C", "C" ), (x,y) -> (x+y).length() == 2 ) .subscribe( System.out::println ); |
l’output prodotto è ora TRUE
, perchè la concatenazione degli elementi emessi generano sempre una stringa di lunghezza 2
.
SkipUntil, SkipWhile, TakeUntil, TakeWhile
Tali operatori sono stati già trattati nell’articolo Primi Passi con RxJava (parte 3), nell’ambito della descrizione degli operatori Skip e Take.