Java 如何将不同观测值的rx.Observable搜索结果合并到单个观测值中?
对于我的android应用程序,我需要一个Observable来聚合7个不同搜索的结果,并作为一个集合发出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
- 对于最终发布,我选择了
,其中ListMultimap
是搜索结果类型的枚举,Content
是用于显示搜索结果的视图模型界面SearchResult
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);