NetBeans 8 Dev を使って Lambda で遊ぶ その4

今回は その2 で作ったプログラムの年齢とバストサイズでフィルタリングし、ファイティングパワーで昇順ソートして生成した List を操作してみます。

といっても何も大したことはしていません。

とりあえず下記コードを追加しました。

jp\yucchi\mylambdasample\MyLambdaSample.java

        // MyBestMember の FightingPower の要素数を取得
        System.out.println("<-- MyBestMember の FightingPower の要素数を取得 -->");
        long count = member.parallelStream().filter(m -> m.getGender() == MyTeam.Sex.FEMALE
                && m.getAge() >= 16
                && m.getAge() <= 29
                && m.getBreast() >= 76)
                .map(MyTeam::getFightingPower)
                .count();
        System.out.println("要素数は " + count + " です。");



        // MyBestMember の FightingPower 最初の要素を取得 (最小値)
        System.out.println("<-- MyBestMember の FightingPower 最初の要素を取得 -->");
        int collect = member.parallelStream().filter(m -> m.getGender() == MyTeam.Sex.FEMALE
                && m.getAge() >= 16
                && m.getAge() <= 29
                && m.getBreast() >= 76)
                .map(MyTeam::getFightingPower)
                .sorted(Integer::compareTo)
                .collect(Collectors.toList()).get(0);
        System.out.println(collect);
        
        
        // MyBestMember の FightingPower 最後の要素を取得 (最大値)
        System.out.println("<-- MyBestMember の FightingPower 最後の要素を取得 -->");
        int collect2 = member.parallelStream().filter(m -> m.getGender() == MyTeam.Sex.FEMALE
                && m.getAge() >= 16
                && m.getAge() <= 29
                && m.getBreast() >= 76)
                .map(MyTeam::getFightingPower)
                .sorted(Integer::compareTo)
                .collect(Collectors.toList()).get((int) (count - 1));
        System.out.println(collect2);


        // MyBestMember の FightingPower 全要素を表示
        System.out.println("<-- MyBestMember の FightingPower 全要素を取得 -->");
        List collect3 = member.parallelStream().filter(m -> m.getGender() == MyTeam.Sex.FEMALE
                && m.getAge() >= 16
                && m.getAge() <= 29
                && m.getBreast() >= 76)
                .map(MyTeam::getFightingPower)
                .sorted(Integer::compareTo)
                .collect(Collectors.toList());
        System.out.println(collect3);

    }
}

要素数は stream オブジェクトのエレメント数を count() メソッドで取得しただけです。

戻り値が long なので要注意です。

これを利用して新しく生成された List<Integer> オブジェクトを操作して最小値と最大値を求めています。

ここで long の count を int にキャストしているのがちょっとアレですね・・・

もっとスマートな方法があるのかもしれません。

最後は新しく生成された List<Integer> オブジェクトを表示させただけです。

結局、stream でゴニョゴニョやってそれで新しい List にしてしまえば今までどおりチョメチョメ操作できてしまうってことかな?

ほとんど Lambda とは関係ない内容になってますが stream オブジェクトの要素数の取り方ってことでお茶を濁します。( ̄。 ̄;)

あっ、ちなみに実行結果は次のようになります。

<– MyBestMember の FightingPower の要素数を取得 –>
要素数は 7 です。
<– MyBestMember の FightingPower 最初の要素を取得 –>
66
<– MyBestMember の FightingPower 最後の要素を取得 –>
89
<– MyBestMember の FightingPower 全要素を取得 –>
[66, 75, 76, 80, 85, 85, 89]

Hatena タグ: ,

NetBeans 8 Dev を使って Lambda で遊ぶ その3

今日も NetBeans 8 Dev を使って Lambda で遊んでみます。

せっかく優秀な統合開発環境を使ってるんだからその機能を使って Lambda の並行処理がちゃんとされているか確認します。

決して疑ってる訳ではございません。

でも、この眼でしっかり確認してみたいだけです。

ってことで昨日作ったプログラムをちょこっと変更して本当に Fork / join Framework が呼び出されているか見てみます。

jp\yucchi\mylambdasample\MyLambdaSample.java

        // テスト用メンバーを作成
        for (int i = 0; i < 20_000_000; i++) {
            member.add(
                    new MyTeam(
                    "TEST" + i,
                    LocalDate.of(1995, 1, 1),
                    MyTeam.Sex.FEMALE,
                    90,
                    random.nextInt(20_000_000)));
        }

        // MyBestMember FightingPower 最大値を表示
        System.out.println("<-- MyBestMember FightingPower 最大値を表示 -->");
        long startTime = System.nanoTime();
        Integer reduce = member.stream().filter(m -> m.getGender() == MyTeam.Sex.FEMALE
                && m.getAge() >= 16
                && m.getAge() <= 29
                && m.getBreast() >= 76)
                .map(MyTeam::getFightingPower)
                .reduce(0, Math::max);
        System.out.println(reduce);
        long time = System.nanoTime() - startTime;
        System.out.println((int) (time * 1e-9) / 3_600 + "時間"
                + (int) ((time * 1e-9) / 60) % 60 + "分"
                + (int) (time * 1e-9 % 60) + "秒"
                + Double.toString((time * 1e-9 % 60) % 1).substring(2));
    }
}

このようにテスト用メンバーを適当に追加して strean() メソッドを使った処理と parallelStream() メソッドを使った場合の違いを確認します。

まず、stream() メソッドを使った時の実行結果は次のようになりました。

run:
<– MyBestMember FightingPower 最大値を表示 –>
19999999
0時間0分41秒8805609010000026
BUILD SUCCESSFUL (total time: 1 minute 0 seconds)

次に昨日のように parallelStream() メソッドを使った場合は

run:
<– MyBestMember FightingPower 最大値を表示 –>
19999999
0時間0分20秒9766124870000006
BUILD SUCCESSFUL (total time: 43 seconds)

このように parallelStream() メソッドを使った方が高速に処理されることが確認できました。

このようにはっきりとした違いが確認できたので次はその仕組みである parallelStream() メソッドを使うと

Fork / join Framework が呼び出されて並行処理をしているところを NetBeans のプロファイラにて暴き出してみてみます。

まず、貧相な stream() メソッドを使った場合からみてみます。

次に贅沢な parallelStream() メソッドを使った場合はこうなります。

このように parallelStream() メソッドを使った場合は  Fork / join Framework が呼び出されているのが解ります。

stream() メソッドの存在価値ってどうなんでしょう?

贅沢な parallelStream() メソッドを使っていればいいのかな?

使い分けシチュエーションがちょっと解りません。

今時、携帯電話さえマルチコアになってるんだからとりあえず parallelStream() メソッドを使っとけばいいのか?

とりあえず Lambda を使えばこのような並行処理プログラミングを意識しないでも簡単に実装できてしまうってことね。

cludia_6_001

Hatena タグ: ,