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

NetBeans 8 Dev を使って Lambda で遊ぶ

NetBeans で Lambda がお気楽に試せる時代がやってきたので今日もちょこっとだけ遊んでみました。

先日チュートリアルを試してみたんだけど途中で上手くいかなかったので今度はシステムプロパティを取得するプログラムを組んでみた。

コードは下記のようにとりあえず Lambda を使わないもので組んだ。

jp\yucchi\printsystemprop\PrintSystemProp.java
package jp.yucchi.printsystemprop;

import java.util.Properties;

public class PrintSystemProp {

    public static void main(String[] args) {
        Properties properties = System.getProperties();
        for ( Object key: properties.keySet() ) {
                        Object value = properties.get( key );
                        System.out.println( key + ": " + value );
                }     
    }
}


実行結果は次のようになる。

java.specification.vendor: Oracle Corporation
java.endorsed.dirs: C:\jdk1.8.0\jre\lib\endorsed
java.vm.specification.version: 1.8
java.vm.specification.name: Java Virtual Machine Specification
java.vendor.url: http://java.oracle.com/
sun.java.launcher: SUN_STANDARD
awt.toolkit: sun.awt.windows.WToolkit
java.vendor: Oracle Corporation
java.io.tmpdir: C:\Users\Yucchi\AppData\Local\Temp\
java.class.path: C:\Users\Yucchi\Documents\NetBeansProjects\PrintSystemProp\build\classes
sun.arch.data.model: 64
user.name: Yucchi
os.version: 6.2
java.vendor.url.bug: http://bugreport.sun.com/bugreport/
os.name: Windows 8
sun.boot.library.path: C:\jdk1.8.0\jre\bin
java.awt.graphicsenv: sun.awt.Win32GraphicsEnvironment
java.library.path: C:\jdk1.8.0\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files\Java\jdk1.7.0_17\bin;C:\Program Files (x86)\Windows Live\Shared;C:\Program Files (x86)\QuickTime\QTSystem\;C:\Program Files (x86)\JustSystems\JSLIB32;C:\Program Files (x86)\Windows Kits\8.0\Windows Performance Toolkit\;C:\Program Files (x86)\Microsoft SQL Server\110\Tools\Binn\;C:\Program Files (x86)\Microsoft SQL Server\110\DTS\Binn\;.
user.home: C:\Users\Yucchi
sun.os.patch.level:
sun.cpu.isalist: amd64
java.vm.vendor: Oracle Corporation
user.country: JP
java.vm.version: 25.0-b19
path.separator: ;
sun.java.command: jp.yucchi.printsystemprop.PrintSystemProp
java.home: C:\jdk1.8.0\jre
java.runtime.version: 1.8.0-ea-lambda-nightly-h3500-20130225-b79-b00
line.separator:

java.awt.printerjob: sun.awt.windows.WPrinterJob
file.separator: \
sun.io.unicode.encoding: UnicodeLittle
sun.boot.class.path: C:\jdk1.8.0\jre\lib\resources.jar;C:\jdk1.8.0\jre\lib\rt.jar;C:\jdk1.8.0\jre\lib\sunrsasign.jar;C:\jdk1.8.0\jre\lib\jsse.jar;C:\jdk1.8.0\jre\lib\jce.jar;C:\jdk1.8.0\jre\lib\charsets.jar;C:\jdk1.8.0\jre\lib\jfr.jar;C:\jdk1.8.0\jre\classes
java.vm.info: mixed mode
sun.desktop: windows
java.version: 1.8.0-ea
java.class.version: 52.0
java.specification.name: Java Platform API Specification
file.encoding: UTF-8
sun.cpu.endian: little
user.script:
java.vm.specification.vendor: Oracle Corporation
java.vm.name: OpenJDK 64-Bit Server VM
user.dir: C:\Users\Yucchi\Documents\NetBeansProjects\PrintSystemProp
sun.management.compiler: HotSpot 64-Bit Tiered Compilers
java.runtime.name: OpenJDK Runtime Environment
user.variant:
file.encoding.pkg: sun.io
java.specification.version: 1.8
sun.jnu.encoding: MS932
java.ext.dirs: C:\jdk1.8.0\jre\lib\ext;C:\Windows\Sun\Java\lib\ext
user.timezone:
user.language: ja
os.arch: amd64

とりあえずちゃんと取得できているようだ。

このプログラムを NetBeans はラムダ式を使うようにお勧めしてくれます。

Use Functional Operation をクリックすると

1

素敵な未来の Java コードに変換してくれます。

2

さて、このままではおもしろくないので キーが sun からはじまるシステムプロパティだけを取得するようにしてみます。

Stream インタフェースが活躍してくれます。

filter()、forEach() を使ってこのように篩い分けをしてくれます。

慣れるまでは違和感がありますが近い将来はこのようなコードを組む時代がそこまでやってきているようです。

jp\yucchi\printsystemprop\PrintSystemProp.java
package jp.yucchi.printsystemprop;

import java.util.Properties;

public class PrintSystemProp {

    public static void main(String[] args) {
        Properties properties = System.getProperties();
        properties.keySet()
                .stream().filter(key  -> key.toString().startsWith("sun"))
                .forEach((key)  
            -> {
            Object value = properties.get(key);
            System.out.println(key + ": " + value);
        });
    }
}

実行結果は

sun.io.unicode.encoding: UnicodeLittle
sun.boot.class.path: C:\jdk1.8.0\jre\lib\resources.jar;C:\jdk1.8.0\jre\lib\rt.jar;C:\jdk1.8.0\jre\lib\sunrsasign.jar;C:\jdk1.8.0\jre\lib\jsse.jar;C:\jdk1.8.0\jre\lib\jce.jar;C:\jdk1.8.0\jre\lib\charsets.jar;C:\jdk1.8.0\jre\lib\jfr.jar;C:\jdk1.8.0\jre\classes
sun.management.compiler: HotSpot 64-Bit Tiered Compilers
sun.java.command: jp.yucchi.printsystemprop.PrintSystemProp
sun.arch.data.model: 64
sun.jnu.encoding: MS932
sun.cpu.endian: little
sun.os.patch.level:
sun.desktop: windows
sun.cpu.isalist: amd64
sun.java.launcher: SUN_STANDARD
sun.boot.library.path: C:\jdk1.8.0\jre\bin

とりあえず目的は果たしているようです。

ただし、私はあまり Lambda のことを調べてないので上記のコードで正しいのか自信ありません。

詳しい人がこれをご覧になっていてもっと良い方法があるんでしたらご指摘くださると嬉しいです。

Hatena タグ: ,