RxJavaあるある

# はじめに

自分用のメモとしてですがRxJavaでつまづいたこと、よくあることなどを書きます
例として出してるコードは言いたいところ以外は省略します、あくまでイメージを掴むようと思ってください

# そもそもRxJavaとは

リアクティブプログラミングをJavaで行うためのもの。

__リアクティブプログラミングとは__
先に処理だけ準備しておいてデータが来た時に準備しておいた処理を行うイメージ。
工場みたいに各工程の機械が設置されてて、製品が流れてきたタイミングで勝手に実行されるような。

処理を準備しているだけなので↓だけ書いても実行されない。
``` Java
Single.just(1).doOnSuccess(System.out::println);
```

subscribe()することで初めてデータが流れてきて処理が実行される。

``` Java
Single.just(1).doOnSuccess(System.out::println)
 .subscribe();
// 1
```

# よく使うものたち

大体使われるのは以下の4つ。

## Single

1つのデータが入っている。0でもnでもなく1つ。
複数のデータもList型にすることで1つのListとして扱える。

## Maybe

0 or 1つのデータが入ってる。Optionalみたいな感じ。
0の場合はdoOnComplete()、1の場合はdoOnSuccess()が実行される。
Single要素にfilterをかけるとMaybeになる。処理を分岐させるときに使ったりする。
map()、flatMap()などは0の場合は実行されない。
nullを入れるとエラー。

## Observable

複数要素の集合。Streamみたいな感じ。
Maybe、Singleの集合でもある。
SingleをfilterするとMaybeになるが、ObservableにfilterをかけてもObservableのまま。
（集合からその要素が消えるだけ）

## Flowable

ほぼObservableと同じ。大量のデータが流れてくる場合にはこっちを使う。
バックプレッシャー機能があるので、1億件のデータが流れてきたとしても100件ずつ取り出して
処理することでメモリがパンクしないように制御できる。

# あるある

RxJava入門者がつまづきがちな話。

## mapとflatMapなにが違うの

mapは1:1変換、flatMapは1:N変換。と言われてもイメージしづらいすよね。

### map()

mapは流れてきたデータそのものを変換するだけ。
Single\<X\>のXの部分だけを変えるイメージ。
なので`.map(i -> Single.just("a"))`ってするとSingle\<Single\<String\>\>になる。

``` Java
Single.just(1) // Single<Integer>:1
 .map(String::valueOf) // Single<String>:"1"
 .doOnSuccess(System.out::println) 
 .subscribe();
// 1

Single.just(1) // Single<Integer>:1
 .map(i -> List.of(1, 2, 3)) // Single<List<Integer>>:[1, 2, 3]
 .doOnSuccess(System.out::println) 
 .subscribe();
// [1, 2, 3]

Observable.fromIterable(List.of(1, 2, 3)) // Observable<Integer>:[1, 2, 3]
 .map(i -> List.of(i, i * 2)) // Observable<Integer>:[[1, 2], [2, 4], [3, 6]]
 .doOnNext(System.out::println) 
 .subscribe();
// [1, 2]
// [2, 4]
// [3, 6]
```

### flatMap()

変換した値を新たに集合に加えるイメージ。
Singleだと戻す値がSingleでネストされてしまう場合のSingleを取り外すぐらいにしか使わないかも。

``` Java
Single.just(1) // Single<Integer>:1
 .flatMap(i -> Single.just(i * 2)) // Single<Integer>:2
 .doOnSuccess(System.out::println) 
 .subscribe();
// 2

Observable.fromIterable(List.of(1, 2, 3)) // Observable<Integer>:[1, 2, 3]
 .flatMap(i -> Observable.fromIterable(List.of(i, i * 2))) // Observable<Integer>:[1, 2, 2, 4, 3, 6]
 .doOnNext(System.out::println) 
 .subscribe();
// 1
// 2
// 2
// 4
// 3
// 6
```

## 処理が動かない
### subscribe漏れ

上でも書きましたが処理を準備しているだけでは実行までされません、subscribeしましょう
``` Java
Single.just(1).doOnSuccess(System.out::println)
 .subscribe();
```

### 処理が流れに乗っていない

これもsubscribe漏れと同じといえば同じなんですがわりとやりがちです

``` Java
private Single<String> func() {
 return Single.just("a").doOnSuccess(System.out::println);
}

Single.just(1)
 .map(i -> {
  func(); // ここがsubscribeされない
  return i;
 })
 .subscribe();
```

上記処理のmap内で構築してるSingleはsubscribeされていないので実行されません
チェーンがつながっていればまとめてsubscribeされるので、実行させたいなら↓のように書きましょう

``` Java
private Single<String> func() {
 return Single.just("a").doOnSuccess(System.out::println);
}

Single.just(1)
 .flatMap(i -> func())
 .subscribe();
// a
```

ちなみにfunc()内でもsubscribeすればどちらも実行されますが、その場合は2つのsubscribeが別々のスレッドで実行されるので意図しない挙動となる可能性の考慮が必要です

``` Java
private Single<String> func() {
 return Single.just("a").doOnSuccess(System.out::println)
         .subscribe();
}
```

### Single\<Single\>になってしまってる

これも結局subscribeされてないってことなんですが

``` Java
Single.just(1)
 .map(i -> Single.just("a").doOnSuccess(System.out::println)) // Single<Single<String>>
 .subscribe();
```

map()のところでも書きましたがmap内でSingle型を返すとSingle\<Single\>\>となってしまうので、内側のSingleがsubscribeされずに処理が実行されません
処理を実行させたければflatMapを使ってSingleがネストしないようにしましょう

``` Java
Single.just(1)
 .flatMap(i -> Single.just("a").doOnSuccess(System.out::println)) // Single<<String>
 .subscribe();
// a
```

## Observable → Listで順番が変わる

Observableは各要素に対してあらかじめ準備した処理を並列実行するため順序が保証されません
なのでtoList()を使用してList化すると実行するたびに順序が変化する可能性があります

``` Java
Observable.fromIterable(List.of(1, 2, 3)) // Observable<Integer>:[1, 2, 3]
 .map(i -> i * 2) // Observable<Integer>:[2, 4, 6]
 .toList() // Single<List<Integer>>:[2, 4, 6]? [4, 6, 2]? [6, 4, 2]?
 .doOnSuccess(System.out::println)
 .subscribe();
```

順序を保証したい場合はtoSortedList()を使ってソート順を指定しましょう

``` Java
Observable.fromIterable(List.of(1, 2, 3)) // Observable<Integer>:[1, 2, 3]
 .map(i -> i * 2) // Observable<Integer>:[2, 4, 6]
 .toSortedList(Integer::compareTo) // Single<List<Integer>>:[2, 4, 6]
 .doOnSuccess(System.out::println)
 .subscribe();
```

# おわり

自分用メモですが誰かの理解の参考になれば。
他にも思いついたら追記していきます。