Java 如何将不同观测值的rx.Observable搜索结果合并到单个观测值中?

Java 如何将不同观测值的rx.Observable搜索结果合并到单个观测值中?,java,android,system.reactive,rx-java,Java,Android,System.reactive,Rx Java,对于我的android应用程序,我需要一个Observable来聚合7个不同搜索的结果,并作为一个集合发出 对于最终发布,我选择了ListMultimap,其中Content是搜索结果类型的枚举,SearchResult是用于显示搜索结果的视图模型界面 我是这样做的,但是我不知道有没有RxJava操作符可以做得更干净呢 public Observable<ListMultimap<Content, SearchResult>> getSearchResults(fin

对于我的android应用程序,我需要一个Observable来聚合7个不同搜索的结果,并作为一个集合发出

  • 对于最终发布,我选择了
    ListMultimap
    ,其中
    Content
    是搜索结果类型的枚举,
    SearchResult
    是用于显示搜索结果的视图模型界面
我是这样做的,但是我不知道有没有RxJava操作符可以做得更干净呢

public Observable<ListMultimap<Content, SearchResult>> getSearchResults(final CharSequence charSequence) {
        return Observable.just(charSequence)
                .map(new Func1<CharSequence, ListMultimap<Content, SearchResult>>() {
                    @Override
                    public ListMultimap<Content, SearchResult> call(CharSequence charSequence) {
                        final String searchTerm = charSequence.toString();

                        final ListMultimap<Content, SearchResult> data =
                                MultimapBuilder.enumKeys(Content.class)
                                        .arrayListValues()
                                        .build();

                        for (SearchResult searchResult : SearchBookmarkableRepoImpl.this.getSectionPageSearchResults(searchTerm).toBlocking().first())
                            data.put(Content.SECTION_PAGE, searchResult);

                        for (SearchResult searchResult : SearchBookmarkableRepoImpl.this.getAppendixPageSearchResults(searchTerm).toBlocking().first())
                            data.put(Content.APPENDIX_PAGE, searchResult);

                        for (SearchResult searchResult : SearchBookmarkableRepoImpl.this.getImageSearchResults(searchTerm, ImageType.FIGURE).toBlocking().first())
                            data.put(Content.FIGURE, searchResult);

                        for (SearchResult searchResult : SearchBookmarkableRepoImpl.this.getImageSearchResults(searchTerm, ImageType.TABLE).toBlocking().first())
                            data.put(Content.TABLE, searchResult);

                        for (SearchResult searchResult : SearchBookmarkableRepoImpl.this.getImageSearchResults(searchTerm, ImageType.FORM).toBlocking().first())
                            data.put(Content.FORM, searchResult);

                        for (SearchResult searchResult : SearchBookmarkableRepoImpl.this.getGlossarySearchResults(searchTerm, GlossaryType.ACRONYMS).toBlocking().first())
                            data.put(Content.ACRONYM, searchResult);

                        for (SearchResult searchResult : SearchBookmarkableRepoImpl.this.getGlossarySearchResults(searchTerm, GlossaryType.DEFINITIONS).toBlocking().first())
                            data.put(Content.DEFINITION, searchResult);

                        return data;
                    }
                });
    }

假设您将每个搜索类型的单个
可观察
拆分为单独的
可观察
s,您可以使用或中的一个将所有结果收集到单个
可观察
。这将使您能够并行运行搜索,如果您愿意,还可以运行单个搜索

例如,可以将两个
可观察的
串联起来,如下所示:

Observable o1 = Observable.just(1, 2, 3);
Observable o2 = Observable.just(4, 5, 6);
Observable result = o1.concatWith(o2);

可观察的
结果将发出
1,2,3,4,5,6

让我们一步一步来做

为了使它更通用,让我们假设您有一个名为anEnum的对象(=SearchResult)和枚举(=Content)

我已经将ArrayListMultimap用于一个具体的实现,我以前没有使用过它,所以如果有更好的方法向它添加对象,请这样做

第一步:
Observable
Observable

其中doSomething:
private void doSomething(ArrayListMultimap列表)


如果您使用常规列表,转换会容易得多,因为已有一些方法可以为您这样做,如
l1。addAll(l2)
for reduce

问题是,可观察的结果会发出6个不同的项。我需要在最后将所有这些排放汇总成一个
列表
toList()
将收集所有排放的项目并排放这些项目的一个
列表。不能有两种类型的列表(如
list
),但可以
map()
将发出的项映射为
,然后将这些对转换为列表。如果其中一个是整数,另一个是字符串呢?只需(1)和只需(“2”),在连接它们之前,您始终可以
map()
将一个可观察对象映射到另一个类型。
Observable o1 = Observable.just(1, 2, 3);
Observable o2 = Observable.just(4, 5, 6);
Observable result = o1.concatWith(o2);
    private Observable<ArrayListMultimap<anEnum, Object>> getMultiListSectionPageSearchResults(final String searchWord, anEnum anEnum) {
    return getSectionPageSearchResults(searchWord).map(objects -> {
        ArrayListMultimap<anEnum, Object> newList = ArrayListMultimap.create();
        for (Object o : objects) {
            newList.put(anEnum, o);
        }
        return newList;
    });
    }
    Observable<ArrayListMultimap<anEnum, Object>> multiList1 = getMultiListSectionPageSearchResults("one", anEnum.ONE);
    Observable<ArrayListMultimap<anEnum, Object>> multiList2 = getMultiListSectionPageSearchResults("two", anEnum.TWO);
    Observable<ArrayListMultimap<anEnum, Object>> multiList3 = getMultiListSectionPageSearchResults("three", anEnum.THREE);
    Observable<ArrayListMultimap<anEnum, Object>> multiList4 = getMultiListSectionPageSearchResults("four", anEnum.FOUR);
        Observable<ArrayListMultimap<anEnum, Object>> mergedLists = Observable.merge(
            multiList1, multiList2, multiList3, multiList4);
        Observable<ArrayListMultimap<anEnum, Object>> oneList = mergedLists.reduce((l1, l2) -> {
        for (anEnum c : l2.keySet()) {
            for (Object o : l2.get(c)) {
                l1.put(c, o);
            }
        }
        return l1;
        });
oneList.single().subscribe(this::doSomething);