【问题标题】:android rxjava sort list with comparator class带有比较器类的android rxjava排序列表
【发布时间】:2023-03-22 23:25:01
【问题描述】:

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

public class EventParticipantComparator {

    public static class StatusComparator implements Comparator<EventParticipant> {

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

我可以将这个类与经典的 Collections 类一起使用。

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

                    }
                });

【问题讨论】:

    标签: android sorting collections rx-java rx-android


    【解决方案1】:

    如果我没有阅读Collections.sort() 的Javadoc,我会推荐map(list -&gt; Collections.sort (list, comparator)) 之类的东西将其转换为排序数组;这里,map 是 observable 映射器。

    但是,上面的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&lt;EventParticipant&gt; 进行单独和异步排序。

    【讨论】:

    • 嗯,你的方式对我来说看起来不错。你知道 rxjava 的 toSortedList() 函数吗?如何将 StatusComparator 函数传递给 toSortedList() 函数。
    • 如果您愿意,可以使用toSortedList(comparator)。但是,这只有在 observable 中的底层对象是 EventParticipants 而不是列表本身时才有效。你写它的方式,似乎方法getParticipants()的输出是Observable&lt;List&lt;EventParticipant&gt;&gt;
    • 是的,getParticipants() 函数的返回值为Observable&lt;List&lt;EventParticipant&gt;&gt;。感谢您的回答。我接受你的帖子。
    • 在你的sn-p中复制集合的原因是什么?
    • 我不想修改通过引用传递给我们的基础列表。通常,您希望避免副作用,因为它会让使用您的代码的任何人都感到困难。我复制是为了避免这种副作用。
    【解决方案2】:

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

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

    请注意,最好使用 Schedulers.io 进行网络/磁盘写入,使用 Schedulers.computation 进行排序等计算

    【讨论】:

    • 是的,谢谢Schedulers.computation() 提示。
    • 我觉得map()操作应该是flatMap()。
    【解决方案3】:

    我假设getParticipants() 方法返回Observable&lt;List&lt;EventPartcipant&gt;&gt;

    在下面的 sn-p 中,我首先使用 flatMap() 运算符将 Observable&lt;List&lt;EventPartcipant&gt;&gt; 转换为 Observable&lt;EventParticipant&gt;。这个 observable 将每次发出一个 EventParticipant。现在,通过使用 toSortedList() 运算符,我可以一次对两个 EventParticipant 对象进行操作,就像 Comparator&lt;EventParticipant&gt;::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.
                    }
        });
    

    【讨论】:

      【解决方案4】:

      还有另一种排序列表的方法

      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】:

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

        【讨论】:

          【解决方案6】:

          你也可以这样做:

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

          科特林:

          list.sortBy { it.name }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-07-25
            • 2021-09-04
            • 2014-07-11
            • 1970-01-01
            • 2014-11-21
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多