Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rxJava transform List to Map

I have list coming back from a REST endpoint. I need to break that list down into categories (category is an item in each entry of the list). Individual categories will be written to a cache for faster lookup later.

I didn't know if I could .map() the entries and supply multiple filter() or some type of case statement to put the category entries in the right bucket.

Does something like this sound reasonable to implement with rxJava?

UPDATE: Non-working version

private Map<String, List<VideoMetadataInfoEntity>> buildCategories( Observable<List<VideoMetadataInfoEntity>> videoList ) {

    Map<String, List<VideoMetadataInfoEntity>> categoryMap = new HashMap<>();
    videoList
            .flatMap( Observable::from )
            .subscribe( videoMetadataInfoEntity -> mapCategory(videoMetadataInfoEntity, categoryMap ) );

    Observable.just( categoryMap )
            .doOnNext( saveCategoriesToCacheAction );

    return categoryMap;
}

These fire in sequence, however, and this is my understanding, the second observable is not sending anything the saveCategoriesToCacheAction since it hasn't subscribed to the result of the first observable.

I am starting to think I should modify my cache strategy. The list will always have all the details. The service doesn't provide me a subset that I can use for listing and then another call to get the full details. It is either full list or full details for one item. It might be a better approach to just cache each one individually and into their own category caches right now. I was trying to do the map so that this network call could return the requested category, but subsequent calls would come from the cache, until such time as the cache has expired and a new network call refreshes it.

like image 735
dmfrey Avatar asked Jul 09 '26 13:07

dmfrey


1 Answers

My solution is:

Observable.range(1, 20)
            .groupBy(number -> number % 2)
            .flatMap(groupedObservable -> groupedObservable.toList())
            .toMap(list -> list.get(0) % 2);

As a result I have [{0=[2, 4, 6, 8, 10, 12, 14, 16, 18, 20], 1=[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]}]

Explanation:

  • range(1, 20) - creates an observable which emits first twenty numbers
  • groupBy(number -> number % 2) - creates an observable that emits group observables where each group observable holds items grouped with the grouping function(here it is x % 2)
  • flatMap(groupedObservable -> groupedObservable.toList()) - turns each group into an observable that emits all its items as a list
  • toMap(list -> list.get(0) % 2) - creates the map
like image 151
Buckstabue Avatar answered Jul 14 '26 07:07

Buckstabue