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 タグ: ,

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

先日はシステムプロパティを取得するプログラムを組んでみたけど誰からもツッコミが入らなかったのでこのまま

勝手にイケイケでよくあるサンプルコードを JDK 8 ならこんなになるのかって勝手に思い込む遊びをします。

決して良い子のみんなは真似をしないようにね!

とりかえしのつかないことになるといけないからね(爆

今回は Java 8 について Twitter 上で下記のようなつぶやきがあったのでそれも試してみます。

「みんな、Java8のラムダは飾りでメソッド参照こそ本命ということに気づいてきた」

私は新しく使いやすくなる日付関係の Date and Time API が本命だと気付きました。(^_^;)

これも今回ちょこっとだけ使ってみたいと思います。

開発環境はこの前と同じです。

NetBeans 8 Dev の未来を先取りする賢い補完機能にずいぶん助けられます。

Java 8 を気楽に試してみたい人にはお勧めです。

では、今回試してみたプログラムをご覧ください。

素人が組んだものですから生暖かい眼差しで見て間違ってるところやここはこうしたほうがいいよって優しく教えてくれたら感激です。

jp\yucchi\mylambdasample\MyTeam.java
package jp.yucchi.mylambdasample;

import java.time.LocalDate;

public class MyTeam {

    public enum Sex {

        MALE, FEMALE
    }
    String name;
    LocalDate birthday;
    Sex gender;
    int Breast;
    int FightingPower;

    public MyTeam(String name, LocalDate birthday, Sex gender, int Breast, int FightingPower) {
        this.name = name;
        this.birthday = birthday;
        this.gender = gender;
        this.Breast = Breast;
        this.FightingPower = FightingPower;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        LocalDate today = LocalDate.now();
        int age = today.getYear() - birthday.getYear();
        if (birthday.getMonthValue() > today.getMonthValue()
                || birthday.getMonthValue() == today.getMonthValue()
                && birthday.getDayOfMonth()
                > today.getDayOfMonth()) {
            age--;
        }
        return age;
    }

    public Sex getGender() {
        return gender;
    }

    public int getBreast() {
        return Breast;
    }

    public int getFightingPower() {
        return FightingPower;
    }

    void printMyTeam() {
        System.out.println(name + ", " + this.getAge() + "歳" + ", Gender: "
                + this.getGender() + ", Breast Size: " + this.getBreast()
                + ", FightingPower: " + this.getFightingPower());
    }
}

jp\yucchi\mylambdasample\MyLambdaSample.java
package jp.yucchi.mylambdasample;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class MyLambdaSample {

    public static void main(String... args) {
        List member = new ArrayList<>();
        member.add(
                new MyTeam(
                "ほげほげ たこたろう",
                LocalDate.of(1980, 6, 20),
                MyTeam.Sex.MALE,
                90,
                100));
        member.add(
                new MyTeam(
                "壇蜜",
                LocalDate.of(1980, 12, 3),
                MyTeam.Sex.FEMALE,
                90,
                99));
        member.add(
                new MyTeam(
                "北川 景子",
                LocalDate.of(1986, 8, 22),
                MyTeam.Sex.FEMALE,
                78,
                80));
        member.add(
                new MyTeam(
                "綾瀬 はるか",
                LocalDate.of(1985, 3, 24),
                MyTeam.Sex.FEMALE,
                88,
                85));
        member.add(
                new MyTeam(
                "佐々木 希",
                LocalDate.of(1988, 2, 8),
                MyTeam.Sex.FEMALE,
                80,
                85));
        member.add(
                new MyTeam(
                "剛力 彩芽",
                LocalDate.of(1992, 8, 27),
                MyTeam.Sex.FEMALE,
                77,
                75));
        member.add(
                new MyTeam(
                "川口 春奈",
                LocalDate.of(1995, 2, 10),
                MyTeam.Sex.FEMALE,
                75,
                70));
        member.add(
                new MyTeam(
                "堀北 真希",
                LocalDate.of(1988, 10, 6),
                MyTeam.Sex.FEMALE,
                78,
                76));
        member.add(
                new MyTeam(
                "武井 咲",
                LocalDate.of(1993, 12, 25),
                MyTeam.Sex.FEMALE,
                76,
                66));
        member.add(
                new MyTeam(
                "石原 さとみ",
                LocalDate.of(1986, 12, 24),
                MyTeam.Sex.FEMALE,
                82,
                89));
        member.add(
                new MyTeam(
                "深田 恭子",
                LocalDate.of(1982, 11, 2),
                MyTeam.Sex.FEMALE,
                90,
                84));
        
        // MyTeam 全員表示
        System.out.println("<-- MyTeam 全員表示 -->");
        member.stream().forEach((e) -> {
            e.printMyTeam();
        });
        
        // 女性で16歳以上29歳以下さらにバストが76センチ以上
        // のチームメンバーを表示する。
        System.out.println("MyBestMember");
        member.parallelStream().filter( m -> m.getGender() == MyTeam.Sex.FEMALE 
                && m.getAge() >= 16
                && m.getAge() <= 29
                && m.getBreast() >= 76)
                .collect(Collectors.toList())
                .forEach(e -> {
                    System.out.println(e.getName() +", " + e.getAge() + "歳, " 
                            + "Gender : " +e.getGender() + ", " + "Breast Size : " 
                            + e.getBreast() +", FightingPower : " +e.getFightingPower());
                });
        
        
        // MyBestMember の FightingPower を昇順ソート
        System.out.println("<-- MyBestMember FightingPower 昇順ソート -->");
        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())      
                .forEach(System.out::println);
        
        // MyBestMember FightingPower 最大値を表示
        System.out.println("<-- MyBestMember FightingPower 最大値を表示 -->");
        Integer reduce = member.parallelStream().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);
        
        // MyBeatMember を FightingPower 詳細照準ソート
        System.out.println("<-- MyBeatMember を FightingPower 詳細照準ソート -->");
        member.parallelStream().filter( m -> m.getGender() == MyTeam.Sex.FEMALE 
                                && m.getAge() >= 16
                                && m.getAge() <= 29
                                && m.getBreast() >= 76)
                .sorted((o1, o2) -> o1.getFightingPower() - o2.getFightingPower())
                .collect(Collectors.toList())
                .forEach(e -> {
                    System.out.println(e.getName() +", " + e.getAge() + "歳, " 
                            + "Gender : " +e.getGender() + ", " + "Breast Size : " 
                            + e.getBreast() +", FightingPower : " +e.getFightingPower());               
                });
    }
    
}


プログラムの内容にはあまり触れないでくださいね。

私の好みの問題ですから(〃・ω・〃)

既に気付かれた方もいるでしょうが Date and Time API を使うと非常にシンプルで直感的に使えます。

細かい説明はしませんので JavaDoc をさらってご覧になってくださいませ。

カレンダー関係に悩まされてきたそこの あ・な・た !

やっとイライラから解放されるかもしれません。

1

カレンダーをセットするのも簡単になってます。(50行目)

2

今まで月の扱いがうざいなぁって思っていたのがやっと解消されますね。

次に、メソッド参照をみてみましょう。

118行目、120行目、128行目、129行目で使ってます。

:: を使った何かしっくりこない違和感の塊がメソッド参照と呼ばれている新機能です。

引数で渡されたオブジェクトのメソッドを呼ぶ機能のようです。

これは単にコード記述量が少なくなるだけなんだろうか?

他に何かメリットがあるのか良く解りません。

今回は static メソッドを使用してますが特定のオブジェクトのインスタンスメソッドや

特定の型の任意のオブジェクトのインスタンスメソッドが使えるようです。

特定のオブジェクトのメソッド参照は、異なる関数型インターフェースに変換する便利な手段を提供します。

Callable<Path> c = ... 
PrivilegedAction<Path> a = c::call;

任意のオブジェクトのインスタンスメソッド参照は

Arrays.sort(names, String::compareToIgnoreCase);

と引数の数が違います。任意のオブジェクトのメソッド参照には第一引数にインスタンスを渡してます。

要するにラムダ式を書く代わりに既存のメソッドを呼び出すことができるよってことなのかな?

これが Java 8 の本命なのか?

私が知らないもしくは理解が足らないのでもっと便利で素敵な使い方があるのだろうか?

ああ!今日も眠れそうにないなw

3

138行目の sorted メソッドがしっくりこないけどどうしたらいいのか解らないので適当にやったら期待通りに動いてしまった。( ̄。 ̄;)

さて、長くなるけど一応このプログラムの実行結果を載せておきます。

run:
<– MyTeam 全員表示 –>
ほげほげ たこたろう, 32歳, Gender: MALE, Breast Size: 90, FightingPower: 100
壇蜜, 32歳, Gender: FEMALE, Breast Size: 90, FightingPower: 99
北川 景子, 26歳, Gender: FEMALE, Breast Size: 78, FightingPower: 80
綾瀬 はるか, 27歳, Gender: FEMALE, Breast Size: 88, FightingPower: 85
佐々木 希, 25歳, Gender: FEMALE, Breast Size: 80, FightingPower: 85
剛力 彩芽, 20歳, Gender: FEMALE, Breast Size: 77, FightingPower: 75
川口 春奈, 18歳, Gender: FEMALE, Breast Size: 75, FightingPower: 70
堀北 真希, 24歳, Gender: FEMALE, Breast Size: 78, FightingPower: 76
武井 咲, 19歳, Gender: FEMALE, Breast Size: 76, FightingPower: 66
石原 さとみ, 26歳, Gender: FEMALE, Breast Size: 82, FightingPower: 89
深田 恭子, 30歳, Gender: FEMALE, Breast Size: 90, FightingPower: 84
<—MyBestMember –>
北川 景子, 26歳, Gender : FEMALE, Breast Size : 78, FightingPower : 80
綾瀬 はるか, 27歳, Gender : FEMALE, Breast Size : 88, FightingPower : 85
佐々木 希, 25歳, Gender : FEMALE, Breast Size : 80, FightingPower : 85
剛力 彩芽, 20歳, Gender : FEMALE, Breast Size : 77, FightingPower : 75
堀北 真希, 24歳, Gender : FEMALE, Breast Size : 78, FightingPower : 76
武井 咲, 19歳, Gender : FEMALE, Breast Size : 76, FightingPower : 66
石原 さとみ, 26歳, Gender : FEMALE, Breast Size : 82, FightingPower : 89
<– MyBestMember FightingPower 昇順ソート –>
66
75
76
80
85
85
89
<– MyBestMember FightingPower 最大値を表示 –>
89
<– MyBeatMember を FightingPower 詳細昇順ソート –>
武井 咲, 19歳, Gender : FEMALE, Breast Size : 76, FightingPower : 66
剛力 彩芽, 20歳, Gender : FEMALE, Breast Size : 77, FightingPower : 75
堀北 真希, 24歳, Gender : FEMALE, Breast Size : 78, FightingPower : 76
北川 景子, 26歳, Gender : FEMALE, Breast Size : 78, FightingPower : 80
綾瀬 はるか, 27歳, Gender : FEMALE, Breast Size : 88, FightingPower : 85
佐々木 希, 25歳, Gender : FEMALE, Breast Size : 80, FightingPower : 85
石原 さとみ, 26歳, Gender : FEMALE, Breast Size : 82, FightingPower : 89
BUILD SUCCESSFUL (total time: 0 seconds)

では、そろそろ寝ようかな。(眠れたら幸せになれるかも)

Hatena タグ: ,