如何将一个Observable <resultset>收集到Map

时间:2017-06-06 14:06:40

标签: rx-java vert.x

我试图从Vertex AsyncSqlClient中收集Observable<ResultSet> 到HashMap。

Map<String, Integer> map = Maps.newHashMap();
asyncSQLClient
        .getConnectionObservable()
        .flatMap(sqlConnection -> sqlConnection.queryObservable("select a, b from table")
                .doOnCompleted(sqlConnection::close)
                .doOnError(throwable -> log.error("Error while querying.", throwable)))
        .flatMap(resultSet -> Observable.from(resultSet.getRows()))
        .toBlocking()
        .forEach(row -> map.put(row.getString("a"), row.getInteger("b")));

但这似乎永远阻止了。

在搜索了一段时间后没有任何结果,你介意借给我一只手吗?

1 个答案:

答案 0 :(得分:1)

正如@Phoenix Wang评论的那样,forEach()方法will block until Observable will completes。意味着如果你有Observable发出无限项,或者你有一个Observable错误地发出onCompleted来表示Observable完成,它将永远阻止。

这可能是由getConnectionObservable()方法实施引起的,如果它创建了自定义Observable,例如使用Observable.create(),则必须先致电onCompleted()物品被发出。

无论如何,你应该知道toBlocking()会阻塞和等待,这可能不适合生产代码(因为它打破了反应的所有目的),你可以达到同样的目的reduce()

 asyncSQLClient
            .getConnectionObservable()
            .flatMap(sqlConnection -> sqlConnection.queryObservable("select a, b from table")
                    .doOnCompleted(sqlConnection::close)
                    .doOnError(throwable -> log.error("Error while querying.", throwable)))
            .flatMap(resultSet -> Observable.from(resultSet.getRows()))
            .reduce(Maps.newHashMap(), (map, o) -> map.put(row.getString("a"), row.getInteger("b")))
            .subscribe(map -> {
                        //do something with map
                    }
            );

请注意,您仍然需要解决onCompleted问题,因为reduce也会期望Observable完成,并会在源Observable完成时发出信号项。
其他选项是使用scan()(只需用扫描替换reduce),使用扫描,您将获得使用源Observable发出的每个项目的排放,这意味着您将累积项目以便随时间映射。