使用 RxJava 计算百分比份额

Calculating percentage shares with RxJava

假设我有以下数据:

Map<String, Integer> counts = new HashMap<>();
counts.put("one", 1);
counts.put("two", 2);
counts.put("three", 3);

我想输出每个类别的百分比,例如:

one: 1/6 = 0.17
two: 2/6 = 0.33
three: 3/6 = 0.5

如何使用 RxJava 高效地计算每个类别的百分比份额?

Note that this is a contrived example, where it is not trivial to reprocess the source data (which actually already comes to me as an Observable).

非常感谢您提供的任何帮助, 段.

到目前为止我已经尝试过的事情

我 运行 遇到的问题是,对于我的 Observable 集,我总是需要在合并它们以计算总数后返回并重新处理各个类别。我已经尝试为此目的发布和使用主题,但在每种情况下都需要在计算百分比之前计算总数(即阻塞)意味着我的 .connect() 或 onNext() 永远不会 运行.

下面的代码获取流 {"one"、"two"、"one"} 并输出:

WithPercent [value=one, percent=66.66666666666667]
WithPercent [value=two, percent=33.333333333333336]

可运行class:

import rx.Observable;

public class Main {

    public static void main(String[] args) throws InterruptedException {
        Observable.just("one", "two", "one")
                .groupBy(x -> x)
                .flatMap(g -> g.count()
                        .map(n -> new WithCount<String>(g.getKey(), n)))
                // now get a list of the counts by key
                .toList()
                // iterate the list and get totals, calculate percents and emit
                .flatMap(list -> {
                    int total = list.stream().mapToInt(wc -> wc.count).sum();
                    return Observable.from(list).map(
                            wc -> new WithPercent<String>(wc.value, 100.0 * wc.count / total));
                }).subscribe(System.out::println);
    }

    private static class WithCount<T> {
        final T value;
        final int count;

        WithCount(T value, int count) {
            this.value = value;
            this.count = count;
        }
    }

    private static class WithPercent<T> {
        final T value;
        final double percent;

        WithPercent(T value, double percent) {
            this.value = value;
            this.percent = percent;
        }

        @Override
        public String toString() {
            return "WithPercent [value=" + value + ", percent=" + percent + "]";
        }

    }
}