2

I've a code:

val d = Single
            .zip<List<X>, Optional<Y>, DataContent>(
                    xSingle,
                    YSingle,
                    BiFunction { x, y ->
                        val b = if (y.isPresent()) {
                            y.get()
                        } else {
                            null
                        }
                        return@BiFunction DataContent(x, b)
                    })
            .subscribe({ data ->
                ...
            }, { t ->
                ...
            })

I've heard, that using Optional to check null value as shown in an example, is bad practice. Is that true? Why? Can someone show an alternative using RxJava2?

MaaAn13
  • 264
  • 5
  • 24
  • 54

1 Answers1

5

In general, Optional has a restricted set of use cases and is in danger of being overrused. You can refer to this answer by Java author Brian Goetz to understand these (emphasis added):

But we did have a clear intention when adding this [java.util.Optional] feature, and it was not to be a general purpose Maybe or Some type, as much as many people would have liked us to do so. Our intention was to provide a limited mechanism for library method return types where there needed to be a clear way to represent "no result", and using null for such was overwhelmingly likely to cause errors.

For example, you probably should never use it for something that returns an array of results, or a list of results; instead return an empty array or list. You should almost never use it as a field of something or a method parameter.

In the original example posted, Optional<Y> is used as a method parameter so this is against Java best practices. Besides, Maybe is idiomatic in RxJava.

Assuming you have something like the following:

class X
class Y
data class DataContent constructor(val listOfX: List<X>, val y: Y)

You could write a function like this that would seem to fit your use case:

fun zipToDataContent(maybeListOfX: Maybe<List<X>>, maybeY: Maybe<Y>): Maybe<DataContent> =
        Maybe.zip<List<X>, Y, DataContent>(
                maybeListOfX,
                maybeY,
                BiFunction { listOfX, y -> DataContent(listOfX, y) })

Tests:

@Test
fun testZipToDataContentWithRealY() {
    val x = X()
    val y = Y()

    val maybeListOfX = Maybe.just(listOf(x))
    val maybeY = Maybe.just(y)

    zipToDataContent(maybeListOfX, maybeY).test()
            .assertOf {
                Maybe.just(DataContent(listOf(x), y))
            }
}

@Test
fun testZipToDataContentWithEmptyY() {
    val x = X()

    val maybeListOfX = Maybe.just(listOf(x))
    val maybeY = Maybe.empty<Y>()

    zipToDataContent(maybeListOfX, maybeY).test()
            .assertOf {
                Maybe.empty<DataContent>()
            }
}
Community
  • 1
  • 1
David Rawson
  • 20,912
  • 7
  • 88
  • 124