.flatMap() parts of the flow can become really complicated. Often, they contain nested calls to multiple .map(), Observable.just(), and other functions.
This makes the .flatMap() Function interfaces a prime candidate for simplification by method extraction. At the moment, consider the tweet retrieval part (the version that doesn't use for loop to filter tweets):
observeTwitterStream(configuration, filterQuery)
.sample(2700, TimeUnit.MILLISECONDS)
.map(StockUpdate::create)
.flatMapMaybe(update -> Observable.fromArray(trackingKeywords)
.filter(keyword ->
update.getTwitterStatus().toLowerCase()
.contains(keyword.toLowerCase()))
.map(keyword -> update)
.firstElement()
)
It has such a flow where the following bit can be extracted to make the bigger tweet retrieval flow simpler:
.flatMapMaybe(update -> Observable.fromArray(trackingKeywords)
.filter(keyword -> update.getTwitterStatus()
.toLowerCase().contains(keyword.toLowerCase()))
.map(keyword -> update)
.firstElement()
)
We will do that by introducing a method:
skipTweetsThatDoNotContainKeywords(trackingKeywords)
So, the .flatMapMaybe() call becomes as follows:
.flatMapMaybe(skipTweetsThatDoNotContainKeywords(trackingKeywords))
The body of such a method will be as follows:
@NonNull
private Function<StockUpdate, MaybeSource<? extends StockUpdate>> skipTweetsThatDoNotContainKeywords(String[] trackingKeywords) {
return update -> Observable.fromArray(trackingKeywords)
.filter(keyword -> update.getTwitterStatus()
.toLowerCase().contains(keyword.toLowerCase()))
.map(keyword -> update)
.firstElement();
}
Again, this can be done very easily using the IDE refactoring functionality.