Android rxjava sort list with comparator class

I started using rxjava with my Android projects. I need to sort the list of events from an api call. I wrote a comparator class to sort the list:

public class EventParticipantComparator { public static class StatusComparator implements Comparator<EventParticipant> { @Override public int compare(EventParticipant participant1, EventParticipant participant2) { return participant1.getStatus() - participant2.getStatus(); } } } 

I can use this class with the classic Collections class.

 Collections.sort(participants, new EventParticipantComparator.StatusComparator()); 

How can I achieve this situation in a reactive way? also, if there is any way to sort the list asynchronously, I prefer this way.

Reactive path without sort list:

 dataManager.getEventImplementer().getParticipants(event.getId()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<List<EventParticipant>>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(List<EventParticipant> eventParticipants) { } }); 
+10
android collections sorting rx-java rx-android
source share
5 answers

If I hadn't read the Javadoc for Collections.sort() , I would recommend something like map (list โ†’ Collections.sort(list, comparator)) to convert it to a sorted array; here map is an observable converter.

However, the sort method above is an in-place sorting algorithm that affects the underlying array, rather than returning a fully sorted array. So instead you should do something like this:

 dataManager.getEventImplementer().getParticipants(event.getId()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .map(unsortedList -> { List<EventParticipant> sortedList = new ArrayList<>(unsortedList); Collections.sort(sortedList, new EventParticipantComparator.StatusComparator()); return sortedList; }) .subscribe(new Subscriber<List<EventParticipant>>() { // ... etc. }); 

This sorts each incoming List<EventParticipant> individually and asynchronously.

+14
source share

This solution is similar to the accepted answer, but uses the Rx operators to 1) partition the array into objects; 2) sorting by specimen; comparable implementation; 3) do this according to a dedicated stream of calculations;

 dataManager.getEventImplementer().getParticipants(event.getId()) .flatMap(Observable::from) .toSortedList() .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(sortedList -> {...}, error -> {...}); 

Note that he prefers to use Schedulers.io for recording on a network / disk, Schedulers.computation for calculations such as sorting

+13
source share

I assume the getParticipants() method returns an Observable<List<EventPartcipant>> .

In the snippet below, I first convert Observable<List<EventPartcipant>> to Observable<EventParticipant> using the flatMap() operator. This observable will emit each EventParticipant one at a time. Now, using the toSortedList() operator, I can act on two EventParticipant at the same time, as expected, Comparator<EventParticipant>::compareTo .

In other solutions, sort operators are applied after .observeOn(AndroidSchedulers.mainThread()) , which means that the actual sort occurs in the user interface thread.

I changed this so that the API call is executed in the I / O scheduler, sorted in the calculation scheduler, and finally your sorted list in the user interface thread.

 getParticipants().flatMap(new Func1<List<EventParticipant>, Observable<EventParticipant>>() { @Override public Observable<EventParticipant> call(List<EventParticipant> eventParticipants) { return Observable.from(eventParticipants); } }).subscribeOn(Schedulers.io()) .observeOn(Schedulers.computation()) .toSortedList(new Func2<EventParticipant, EventParticipant, Integer>() { @Override public Integer call(EventParticipant eventParticipant, EventParticipant eventParticipant2) { return new StatusComparator().compare(eventParticipant, eventParticipant2); } }).observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<List<EventParticipant>>() { @Override public void call(List<EventParticipant> eventParticipants) { // Your sorted list on UI thread. } }); 
+7
source share

There is also another way to sort the list.

 dataManager.getEventImplementer().getParticipants(event.getId()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .flatMapIterable(participants -> participants) .toSortedList((p1,p2) -> {p1.getStatus() - p2.getStatus()}) .subscribe(new Subscriber<List<EventParticipant>>() { // ... etc. }); 
+5
source share

Kotlin version:

 disposable.add(interactor.getItemList() //It returns Observable<ItemListResponseModel> .compose(threadTransformer.applySchedulers()) .flatMapIterable { list -> list } .toSortedList { p1, p2 -> (p1?.name ?: "").compareTo(p2?.name ?: "") } .subscribe({ items -> //... }, { throwable -> //.. })) 
+1
source share

All Articles