android 带比较器的 rxjava 排序列表 class

android rxjava sort list with comparator class

我开始在我的 android 项目中使用 rxjava。我需要对 api 调用返回的事件列表进行排序。我写了比较器 class 来排序列表:

public class EventParticipantComparator {

    public static class StatusComparator implements Comparator<EventParticipant> {

        @Override
        public int compare(EventParticipant participant1, EventParticipant participant2) {
            return participant1.getStatus() - participant2.getStatus();
        }
    }
}

我可以将此 class 与 classic Collections class.

一起使用
Collections.sort(participants, new EventParticipantComparator.StatusComparator());

我怎样才能用反应方式实现这种情况? 此外,如果有任何方法可以异步排序列表,我会更喜欢这种方式。

没有排序列表的反应方式:

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) {

                    }
                });

如果我没有阅读 Collections.sort(), I would have recommended something like map(list -> Collections.sort (list, comparator)) 的 Javadoc 将其转换为排序数组;这里,map 是可观察映射器。

但是,上面的sort方法是一种就地排序算法,它影响底层数组而不是返回完全排序的数组。所以你应该这样做:

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.
            });

这将单独和异步地对每个传入的 List<EventParticipant> 进行排序。

此解决方案与已接受的答案类似,但使用 Rx 运算符 1) 将数组拆分为对象 2) 按实例排序 Comparable 实现 3) 在专用计算线程上执行;

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

请注意,对于 network/disk 写入,最好使用 Schedulers.io,对于排序等计算,Schedulers.computation

我假设 getParticipants() 方法 returns Observable<List<EventPartcipant>>.

在下面的代码片段中,我首先使用 flatMap() 运算符将 Observable<List<EventPartcipant>> 转换为 Observable<EventParticipant>。这个 observable 将一次发射每个 EventParticipant 一个。现在,通过使用 toSortedList() 运算符,我可以一次作用于两个 EventParticipant 对象,就像 Comparator<EventParticipant>::compareTo 期望的那样。

在其他解决方案中,排序运算符在 .observeOn(AndroidSchedulers.mainThread()) 之后应用,这意味着实际排序发生在 UI 线程上。

我对此进行了修改,让 API 调用在 IO 调度程序上执行,在计算调度程序上排序,最后在 UI 线程上执行排序列表。

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.
                }
    });

还有一种排序列表的方法

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.
        });

Kotlin 版本:


    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 ->
            //..
        }))

你也可以这样做:

Observable.from(list)
        .sorted((o1, o2) -> o1.name.compareTo(o2.name))
        .toList()
        .subscribe(
            sortedList -> sortedList,
            error -> error);

科特林:

list.sortBy { it.name }