1

私は一般的にRxJavaとFPにかなり慣れていません。Observable2 つの sを結合するコードを書きたいと思います。整数のセットが 2 つあるとします。

  • [0..4]のモジュロとしてキーセレクターを使用して2(key, value) = {(0,0), (1,1), (0,2),...}
  • [0..9]のモジュロとしてキーセレクターを使用して3(key, value) = {(0,0), (1,1), (2,2), (0,3), (1,4),...}

それらに参加するための私の手順は次のとおりです。

  1. 各セットをそのキーでグループ化します。1 番目のセットは、 キー0とで 2 つのグループを作成します1。2 つ目は、キー01およびで 3 つのグループを作成します2
  2. グループの 2 つのセットのデカルト積を作成し、合計で 6 つのグループのペアをキーとして与えます: 0-00-10-21-0、。1-11-2
  3. 0-0と のみを残して、両側に同じキーを持つペアのみをフィルタリングします1-1
  4. 各ペア内で、左右のグループのデカルト積を作成します。

以下は、デカルト積を計算するためのヘルパー クラスです。

public class Cross<TLeft, TRight, R> implements Observable.Transformer<TLeft, R> {
    private Observable<TRight>      _right;
    private Func2<TLeft, TRight, R> _resultSelector;

    public Cross(Observable<TRight> right, Func2<TLeft, TRight, R> resultSelector) {
        _right = right;
        _resultSelector = resultSelector;
    }

    @Override
    public Observable<R> call(Observable<TLeft> left) {
        return left.flatMap(l -> _right.map(r -> _resultSelector.call(l, r)));
    }
}

参加するコードは次のとおりです。

Observable.range(0, 5).groupBy(i -> i % 2)
        .compose(new Cross<>(Observable.range(0, 10).groupBy(i -> i % 3), ImmutablePair::new))
        .filter(pair -> pair.left.getKey().equals(pair.right.getKey()))
        .flatMap(pair -> pair.left.compose(new Cross<>(pair.right, ImmutablePair::new)))
        .subscribe(System.out::println);

ただし、出力は正しくありません。

(0,0)
(0,3)
(0,6)
(0,9)
(1,1)
(1,4)
(1,7)

を含む行を削除するfilterと、結果はまったくありません。正しい出力は、次のように実行する必要があります。

Observable.range(0, 5)
        .compose(new Cross<>(Observable.range(0, 10), ImmutablePair::new))
        .filter(pair -> pair.left % 2 == pair.right % 3)
        .subscribe(System.out::println);

与える:

(0,0)
(0,3)
(0,6)
(0,9)
(1,1)
(1,4)
(1,7)
(2,0)
(2,3)
(2,6)
(2,9)
(3,1)
(3,4)
(3,7)
(4,0)
(4,3)
(4,6)
(4,9)

誰かが動作を説明できますか? どうもありがとう。

注:org.apache.commons.lang3.tuple.ImmutablePair不思議に思う場合に使用します。

4

1 に答える 1

2

問題は、この設定が許可されていないグループに複数回サブスクライブしようとすることです。オーバーロードの例外が表示されますsubscribe(System.out::println, Throwable::printStackTrace);が、これは常に他のものよりも使用することをお勧めします。以下は、ImmutablePair の別の層を犠牲にして再利用を許可する修正された例です。

Func1<Integer, Integer> m2 = i -> i % 2;
Func1<Integer, Integer> m3 = i -> i % 3;

Observable<ImmutablePair<Integer, Observable<Integer>>> g2 = 
        Observable.range(0, 5).groupBy(m2).map(g -> new ImmutablePair<>(g.getKey(), g.cache()));
Observable<ImmutablePair<Integer, Observable<Integer>>> g3 = 
        Observable.range(0, 10).groupBy(m3).map(g -> new ImmutablePair<>(g.getKey(), g.cache()));

Observable<ImmutablePair<ImmutablePair<Integer, Observable<Integer>>, ImmutablePair<Integer, Observable<Integer>>>> x1 
= g2.compose(new Cross<>(g3, ImmutablePair::new));

Observable<ImmutablePair<ImmutablePair<Integer, Observable<Integer>>, ImmutablePair<Integer, Observable<Integer>>>> x2 
= x1.filter(pair -> pair.left.getKey().equals(pair.right.getKey()));


Observable<ImmutablePair<Integer, Integer>> o = x2.flatMap(pair -> 
pair.left.right.compose(new Cross<>(pair.right.right, ImmutablePair::new)));

o.subscribe(System.out::println, Throwable::printStackTrace);

(長い型については申し訳ありません。Eclipse では、ローカル変数を使用する代わりにそれらをインライン化しようとすると、あらゆる種類の推論の問題が発生します)

于 2015-11-25T10:51:12.893 に答える