Paul Woitaschek Paul Woitaschek - 3 months ago 6
Java Question

Difference between first() and take(1)

I am trying to understand the details of

RxJava
.

Intuitively I expected
first()
and
take(1)
to be equal and do the same. However by digging in the source code
first()
is defined as
take(1).single()
.

What is the
single()
here good for? Doesn't
take(1)
already guarantee to output a single item?

Answer

The difference is that take(1) will relay 0..1 items from upstream whereas first will relay the very first element or emits an error (NoSuchElementException) if the upstream is empty. Neither of them is blocking.

It is true first == take(1).single() where take(1) limits the number of upstream items to 1 and single() makes sure upstream isn't empty.

This example prints "Done" only

Observable.empty().take(1)
.subscribe(System.out::println, Throwable::printStackTrace, 
    () -> System.out.println("Done"));

This example prints "1" followed by "Done":

Observable.just(1).take(1)
.subscribe(System.out::println, Throwable::printStackTrace, 
    () -> System.out.println("Done"));

This example also prints "1" followed by "Done":

Observable.just(1, 2, 3).take(1)
.subscribe(System.out::println, Throwable::printStackTrace, 
    () -> System.out.println("Done"));

This example fails with NoSuchElementException

Observable.empty().first()
.subscribe(System.out::println, Throwable::printStackTrace, 
    () -> System.out.println("Done"));

This example, again, prints "1" followed by "Done":

Observable.just(1).first()
.subscribe(System.out::println, Throwable::printStackTrace, 
    () -> System.out.println("Done"));

This example, again, prints "1" followed by "Done":

Observable.just(1, 2, 3).first()
.subscribe(System.out::println, Throwable::printStackTrace, 
    () -> System.out.println("Done"));

This example prints a stacktrace of NoSuchElementException because the source contained too few elements:

Observable.empty().single()
.subscribe(System.out::println, Throwable::printStackTrace, 
    () -> System.out.println("Done"));

This example prints a stacktrace of IllegalArgumentException because the source contained too many elements:

Observable.just(1, 2, 3).single()
.subscribe(System.out::println, Throwable::printStackTrace, 
    () -> System.out.println("Done"));
Comments