2015-12-18 『Learning Reactive Programming with Java 8』 もくもく読書会(Chapter 2)の振り返り
Learning Reactive Programming With Java 8
- 作者: Nickolay Tsvetinov
- 出版社/メーカー: Packt Publishing
- 発売日: 2015/06/24
- メディア: ペーパーバック
- この商品を含むブログを見る
Chapter 2: Using the Functional Constructions of Java 8
タイトルは「Java 8での関数的な構築の使用」というところか?
Introduction
- 小さい再利用可能な関数を使いながらプログラムを構築すること
- プログラムのロジックは工程を明らかにした小さいもので複雑なアルゴリズムではない
- 状態の使用を最低限に抑える
- Java 8 よりラムダ式の使用が可能になり関数に関数を渡すことが可能になった
この章では下記のトピックを見ていく
Lambda in Java 8
Listが使えるObservable#map(Func1)
のようなメソッドを実装するため、次のようなコードがあったとする。
interface Mapper<V, M> { M map<V value); }
public static <V, M> List<M> map(List<V> list, Mapper<V, M> mapper){ List<M> mapped = new ArrayList<M>(list.size()); for(V v: list){ mapped.add(mapper.map(v); } return mapped; }
これをラムダ式を使わずに実装するには匿名クラスを使わなければならない。これは無駄な行とコードが多い。
また匿名クラス方法の問題の本質はアクションを渡しているのではなくオブジェクトを渡している点にあり、プログラムのすべきことを曖昧にしている。
ラムダ式を使うとシンプルになり、わかりやすくなる。
特にオブジェクトを渡す代わりにアクションが定義されたコードのブロックを渡すことで意図がはっきりする。
ラムダ式
- 関数型インターフェイス = 一つだけのabstractメソッドを持つインターフェイス
- 関数型インターフェイスを引数に持つメソッドに対し、実装したインターフェイスを渡す代わりにラムダ式を渡すことができる
- Java 8 に追加されたインターフェイスのdefaultメソッドを使うことで、既に存在しているインターフェイスを関数型インターフェイスに変更することが楽になる
→ Java 8より前のものだとメソッドが既に実装されているため - ラムダ式はある程度の型推論が使えるので型の定義が不要になるケースがある
- return構文も省略可能
- ラムダ式は匿名クラスの糖衣構文ではなく、JVMに素早くアクセスできるようになっている
- メソッド参照やコンストラクタ参照も使える
メソッド参照/コンストラクタ参照の例
Book::makeBook
// クラスのstaticメソッドbook::read
// インスタンスのメソッドBook::new
// コンストラクタBook::read
// 実際のインスタンスを指定を指定していないインスタンスのメソッド
Functional interfaces in Java 8 and RxJava
- RxJavaはラムダ式が使えるようになっている
- subscribeメソッドに渡すアクションはラムダ式で実装することが可能
- RxJavaの関数型インターフェイスは
rx.functions
パッケージにある - RxJavaの関数型インターフェイスはマーカーインターフェイス
Function
を継承している - RxJavaではConsumer(戻り値なしのアクション)のマーカーインターフェイスとして
Action
も用意してる - RxJavaの関数型インターフェイスは引数が複数持てるように11種類用意されている
Implementing the reactive sum example with lambda
※ ソースは本もしくは著者のGitHub参照
内容はChpter 1と同じだが、かなりシンプルでわかりやすくなる
※ メモ
- 内容はChpter 1と同じと本ではあるが
onComplete
で参照しているsum
が見れなくなっている - Observable#createメソッドをラムダ式で書くには引数のSubscriberの型を定義しないと型がStringではなくObjectになるためコンパイルエラーになる
return Observable .create((Subscriber<? super String> subscriber) -> {
Pure functions and higher order functions
- Rxjavaは多くの関数型プログラミングの考え方を導入している
- より良いReactiveなアプリケーションを作るのに関数型の考え方を学ぶ必要がある
Pure functions
- 戻り値が引数によってのみ決められる関数
- 副作用がない
- idempotence(冪等性
べきとうせい
) = 何度やっても結果が同じ - immutableなオブジェクトを使うことが重要
ただしimmutableなオブジェクトは毎回新しいインスタンスを作るのでメモリが足らなくなる可能性がある
それを避けるには同じオブジェクトを再利用したり、オブジェクトのライフサイクルを短くするなどしないといけない
Higher order functions
- 関数を引数や戻り値に持つ関数
- 高階関数の目的は関数を柔軟にすること
- 同じ振舞を別の型の入力値に適用することが可能になる
- ひとつの関数を使って振舞を変えることが可能
- オブジェクト指向の場合、継承してOverrideしたりする必要があるが、関数型だと高階関数を使って同じ関数を違う引数で呼び、違う振舞を低位することができる。
RxJava and functional programming
- RxJavaは純粋関数や高階関数などの関数型のコンセプトが重要である