Reactor Java 如何不用block将Mono<String>添加到Mono<List<String>>
解决方案
核心逻辑
响应式编程的数据流是懒执行的,不能通过block()阻塞取值,正确的做法是通过响应式操作符组合两个Mono的发布结果,完成列表元素的追加操作。
完整代码实现
你可以直接修改addStudent方法,以下是可直接运行的实现:
import java.util.ArrayList; import java.util.List; import reactor.core.publisher.Mono; public class Classroom { private Mono<List<String>> classroom = Mono.just(new ArrayList<String>()); public void addStudent(Mono<String> student) { // 使用zipWith操作符组合两个Mono的发布结果 classroom = classroom.zipWith(student, (currentList, newStudent) -> { currentList.add(newStudent); return currentList; }); // 如果担心多线程场景下修改原列表引发并发问题,可选择生成新列表的写法 // classroom = classroom.zipWith(student, (currentList, newStudent) -> { // List<String> newList = new ArrayList<>(currentList); // newList.add(newStudent); // return newList; // }); } }
关键注意事项
zipWith操作符会等待classroom和传入的student两个Mono都发布结果后,再执行你定义的合并逻辑,最终返回新的Mono<List<String>>重新赋值给成员变量。- 如果你后续有操作依赖学生添加完成的结果,不建议将
addStudent定义为void类型,建议直接返回组合后的Mono<List<String>>,方便后续链式调用和订阅,优化后的方法如下:
public Mono<List<String>> addStudent(Mono<String> student) { return classroom = classroom.zipWith(student, (currentList, newStudent) -> { currentList.add(newStudent); return currentList; }); }
- 所有响应式操作只有被订阅后才会真正执行,只调用
addStudent方法不会触发列表追加逻辑,示例订阅代码如下:
public static void main(String[] args) { Classroom classroom = new Classroom(); classroom.addStudent(Mono.just("张三")) .subscribe(finalList -> System.out.println("当前班级学生列表:" + finalList)); }
替代实现方案
你也可以用flatMap操作符实现完全相同的效果,写法如下:
public void addStudent(Mono<String> student) { classroom = classroom.flatMap(currentList -> student.map(newStudent -> { currentList.add(newStudent); return currentList; }) ); }
两种实现没有性能差异,你可以根据自己的编码习惯选择。
内容的提问来源于stack exchange,提问作者156420591
相关产品推荐
相关产品推荐

