java - Quarkus/Mutiny 中是否需要递归?
问题描述
我正在尝试使用 Redis 的扫描功能,该功能需要调用,直到返回的光标为“0”。
这种方法有效,但感觉过于复杂 - 有没有一种方法可以在没有递归的情况下做到这一点?
Uni<Object> callScanRecursively(String cursorNum, List<String> results) {
List<String> args = new ArrayList<>(List.of(cursorNum, "MATCH", "*"));
return reactiveRedisClient.scan(args)
.onItem()
.transformToUni(item -> {
List<String> keysList = new ArrayList<>();
item.get(1).forEach(k -> {
keysList.add(k.toString());
});
results.addAll(keysList);
if (item.get(0).toString().equals("0")) {
return Uni.createFrom().item(results);
} else {
String nextCursorNum = item.get(0).toString();
return callScanRecursively(nextCursorNum, results);
}
}
);
}
List<String> results = new ArrayList<>();
String startingCursorRedis = "0";
callScanRecursively(startingCursorRedis, results)
.subscribe()
.with(item ->
LOGGER.info(item)
);
解决方案
当给定条件仍未满足时,您可以使用通过发射器MultiRepeat
收集结果:ReactiveRedisClient#scan
Uni
response.get(0).toString().equals("0")
单向发射器
Multi<String> callScan(String initialCursor) {
final AtomicReference<String> cursorReference = new AtomicReference<>(initialCursor);
return Multi.createBy()
.repeating()
.<AtomicReference<String>, List<String>>uni(
() -> cursorReference,
(state, emitter) -> reactiveRedisClient.scan(List.of(state.get(), "MATCH", "*"))
.subscribe()
.with(response -> {
if (response.get(0).toString().equals("0")) {
cursorReference.set(null);
} else {
state.set(response.get(0).toString());
}
java.util.List<String> keysList = new ArrayList<>();
response.get(1).forEach(k -> keysList.add(k.toString()));
emitter.complete(keysList);
})
)
.whilst(o -> cursorReference.get() != null)
.flatMap(l -> Multi.createFrom().iterable(l));
}
单
如果您不需要对发出的项目进行更多控制,甚至更简单:
Multi<String> callScan(String initialCursor) {
ReactiveRedisClientImpl reactiveRedisClient = new ReactiveRedisClientImpl();
final AtomicReference<String> cursorReference = new AtomicReference<>(initialCursor);
return Multi.createBy()
.repeating()
.uni(
() -> cursorReference,
(state) -> reactiveRedisClient.scan(List.of(state.get(), "MATCH", "*"))
.invoke(response -> {
if (response.get(0).toString().equals("0")) {
cursorReference.set(null);
} else {
state.set(response.get(0).toString());
}
})
.map(response -> {
List<String> keysList = new ArrayList<>();
response.get(1).forEach(k -> keysList.add(k.toString()));
return keysList;
})
)
.whilst(o -> cursorReference.get() != null)
.flatMap(l -> Multi.createFrom().iterable(l));
}
推荐阅读
- elasticsearch - 为多值字段搜索获得正确的相关性
- c# - 列表中每个键值对的计数组
- html - 手持设备上的图像太小并改变比例
- sql - 使用递归查询的存储过程
- java - 如果用户没有正确地将他们的年龄输入控制台,我如何再次询问用户的年龄?
- java - 如何使用 Java 8 流考虑拆分字符串的第一个标记
- functional-programming - Kotlin 索引 while 和 lambda 表示法
- html - 每页有许多 JSON-LD 脚本元素还是一个带有嵌套的元素?
- python - Python 等价于 MATLAB findobj()
- ubuntu - Ubuntu 16.04:配置组以通过 GUI 更改日期,无需管理员权限