torutkのブログ

ソフトウェア・エンジニアのブログ

「Java 8 Lambdas」を読む会第2回にむけて

Java読書会BOFは、6月14日(土)に「Java 8 Lambdas」を読む会(第2回)を神奈川県川崎市の公共会議室(最寄り駅は川崎駅)で開催します。洋書なので、翻訳分担をして当日は日本語訳資料を配布して日本語での朗読となります。
なお、本読書会の参加は、翻訳分担を持たなくても歓迎です。第1回に参加していなくても支障なく参加できます。申し込みはJava読書会BOFサイトで受付中です。

第1回の内容

第1回は、序章、1章、2章、3章の途中(ペーパーバック版で27ページ)まででした。

序章

Java 8のラムダ式とStream APIには、いろいろな立場の人がいろいろな思いを主張していますが、本書の著者の立場は序章の次の一節に表れていると思います。

書籍「Java 8 Lambdas」p.viiから引用

For many people, what Java 8 offers by way of functional programming is incredibly limited: no monads, no language-level lazy evaluation, no additional support for immutability.
As pragmatic programmers, this is fine; what we want is the ability to write libray-level abstractions so we can write simple, clean code that solves business problems.

拙訳

多くの人にとってJava 8が提供する関数型プログラミングの手段はかなり限られたものです。モナドもなく、言語レベルの遅延評価もなく、不変性の追加サポートもありません。
現場のプログラマーにとってはこれがよいのです。私たちが望むのは簡潔でクリーンなコードを書いてビジネス上の問題を解決するためにライブラリレベルの抽象化を記述することができることなのです。

第1章
  • Java 8は複雑なコレクション処理アルゴリズムを書き、またそれを1箇所変えるだけでマルチコアで効率的に実行できるラムダ式(Stream API)が導入された
  • オブジェクト指向プログラミングはデータの抽象化、関数型プログラミングは振る舞いの抽象化→読みやすいコード(HowでなくWhatを表現)
  • コールバックやイベントハンドラを無名クラスで記述する冗長さ、可読性の悪さから解放される
  • デフォルトメソッドはメンテナンスに利便性を
第2章

ラムダ式の最初のコードの例示は、Swingのイベントリスナーを簡潔に記述するものから始まります。

無名クラスで記述したコード(例2-1)

button.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent event) {
        System.out.println("button clicked");
    }
});

ラムダ式で記述したコード(例2-2)

button.addActionListener(event -> System.out.println("button clicked"));

いくつかのインタフェース型でラムダ式を書く例を示し、実質的finalの例を示したあと、関数型インタフェース(Functional Interface)の説明、型推論(Type Inference)の説明と例とが続きます。

第3章(途中)

Stream API、外部イテレーションと内部イテレーションが登場します。

外部イテレーション(拡張for文使用)(例3-1)

int count = 0;
for (Artist artist : allArtists) {
    if (artist.isFrom("London")) {
        count++
    }
}
  • 冗長的(ボイラープレート)
  • 並列処理をするにはすべてのfor文を書き換えなくてはならない
  • プログラマの意図を曖昧にしてしまう(特にネストしたループ)

内部イテレーション(例3-3)

long count = allArtists.stream()
                       .filter(artist -> artist.isFrom("London"))
                       .count();

終端操作(eager operator)がないと何も処理が動かないことの説明(例3-5)

allArtists.stream()
          .filter(artist -> {
              System.out.println(artist.getName());
              return artist.isFrom("London");
          });

これを実行しても何もプリントされません。

  • collect(toList())
  • map
  • filter
  • flatMap
  • maxとmin

いくつかの主要操作の説明が列挙されています。
この本では、操作の意図を読者に伝えるために図が使われています。

flatMap操作(図3-7)

 □                          ○
      flatMap(□ to ○,○)  ○
      -------------------->
 ■             ●
               ●

flatMapは、今までいくつか記事を読んできましたがいまいちピンと来なかったのですが、この本で分かった気になりました。

第2回の予定

書籍のp.27 第3章 A Common Pattern Appearsからです。
翻訳分担を第3章後半でエントリーしたので、来週にむけて翻訳を進めることになります。
外部イテレーションから内部イテレーションへのリファクタリングを行う箇所なので、読んでいて面白いところです。

電子書籍との併用について

今回、課題図書選定から第1回の読書会開催までの期間が2週間と短く、また、Amazon.co.jpで洋書の在庫が切れて取り寄せに数週間かかる状況となっていたこと、Kindle版の価格はペーパーバック版の半額と安いので、電子書籍を購入して読書会に参加した方も多くおりました。

そこで分かったことは、Kindle版には書籍のページ番号がないので、ページ数を言っても場所が伝わらないこと、電子書籍版(PDF)は図がカラーなのに書籍は白黒なので色を使い分けた図がPDF以外では分からなかったことなどがありました。