如何在RxJava中进行递归可观察调用?
我对(一般来说是反应性范式)是相当陌生的,所以请容忍我 假设我有这个如何在RxJava中进行递归可观察调用?,java,reactive-programming,rx-java,observable,Java,Reactive Programming,Rx Java,Observable,我对(一般来说是反应性范式)是相当陌生的,所以请容忍我 假设我有这个News和这个嵌套的Comment数据结构: public class News { public int id; public int[] commentIds; //only top level comments public News(int id, int[] commentIds) { this.id = id; this.commentIds = commentIds; } } pu
News
和这个嵌套的Comment
数据结构:
public class News {
public int id;
public int[] commentIds; //only top level comments
public News(int id, int[] commentIds) {
this.id = id;
this.commentIds = commentIds;
}
}
public class Comment {
public int id;
public int parentId; //ID of parent News or parent comment
public int[] childIds;
public Comment(int id, int parentId, int[] childIds) {
this.id = id;
this.parentId = parentId;
this.childIds = childIds;
}
}
假设我有一个API端点:
getComments(int commentId) //return Observable<Comment> for Comment with ID commentId
**
现在,如果我有News n=News(99,[1,2])
,我如何递归地获取它的所有子级注释?i、 e.获取ID为[1,2,3,4,5,6]的评论?
**
我寻找并偶然发现了这一点:
这是递归函数:
public class FileRecursion {
static Observable<File> listFiles(File f) {
if(f.isDirectory())
return Observable.from(f.listFiles()).flatMap(FileRecursion::listFiles);
return Observable.just(f);
}
public static void main(String[] args) {
Observable.just(new File("/Users/joschneider/Desktop"))
.flatMap(FileRecursion::listFiles)
.subscribe(f -> System.out.println(f.getAbsolutePath()));
}
}
公共类文件递归{
静态可观察列表文件(文件f){
if(f.isDirectory())
返回Observable.from(f.listFiles()).flatMap(FileRecursion::listFiles);
可观察的返回。仅(f);
}
公共静态void main(字符串[]args){
Observable.just(新文件(“/Users/joschneider/Desktop”))
.flatMap(文件递归::列表文件)
.subscribe(f->System.out.println(f.getAbsolutePath());
}
}
它显示了一个如何执行递归可观察调用的示例,但内部函数(f.listFiles()
)是一个阻塞操作(不返回另一个可观察调用)。在我的例子中,内部函数(getComments
)是一个非阻塞函数,返回另一个可观察值。我该怎么做
任何帮助都将不胜感激。这与文章中描述的几乎相同:
Observable<Comment> getInnerComments(Comment comment) {
if (comment.childIds.length > 0)
return Observable.merge(
Observable.just(comment),
Observable.from(comment.childIds)
.flatMap(id -> getComments(id))
.flatMap(this::getInnerComments));
return Observable.just(comment);
}
public static void main(String[] args) {
getComments(1)
.flatMap(this::getInnerComments)
.subscribe(c -> System.out.println(comment.toString()));
}
你搞错了-
listFiles
确实返回了一个可观察的
。嘿,你说得对!我怎么会不知道呢?好的,那么我如何实现这一点……嗯……哦,我是说内部函数f.listFiles()
,它不返回可观测值,对吗?返回observable的是FileRecursion::listFiles
。还是我遗漏了什么?你是对的-那是File#listFiles
,它返回File[]
。Egor,递归只得到了叶注释(即没有任何子项的注释)。看起来像是在递归函数中订阅了非叶注释。有什么想法吗?等等,我没有看到你更新的答案。让我先考虑一下。嗯,你说得对,我还没想过。我编辑了我的答案-现在getInnerComments()
返回传递给它的注释,然后执行其他操作。@HoverPhoenix,等一下,我第一次阅读时不理解你的注释。让我打开我的IDE试试看。你真厉害,伊戈尔。成功了!我缺少的关键点是flatMap
内部flatMap
。此外,现在我明白了为什么需要运算符合并!非常感谢。我已经接受了你的帖子作为答案。是的,我刚刚测试过,效果很好。很高兴我能帮助你!。
Observable<Comment> getInnerComments(Comment comment) {
if (comment.childIds.length > 0)
return Observable.merge(
Observable.just(comment),
Observable.from(comment.childIds)
.flatMap(id -> getComments(id))
.flatMap(this::getInnerComments));
return Observable.just(comment);
}
public static void main(String[] args) {
getComments(1)
.flatMap(this::getInnerComments)
.subscribe(c -> System.out.println(comment.toString()));
}
getNews(99)
.flatMap(news -> Observable.from(news.commentIds))
.flatMap(commentId -> getComments(commentId))
.flatMap(comment -> getInnerComments(comment))
.toList()
.subscribe(commentList -> { });