Java NetBeans
今日も NetBeans 8 Dev を使って Lambda で遊んでみます。
せっかく優秀な統合開発環境を使ってるんだからその機能を使って Lambda の並行処理がちゃんとされているか確認します。
決して疑ってる訳ではございません。
でも、この眼でしっかり確認してみたいだけです。
ってことで昨日作ったプログラムをちょこっと変更して本当に Fork / join Framework が呼び出されているか見てみます。
jp\yucchi\mylambdasample\MyLambdaSample.java
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// テスト用メンバーを作成
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 を使えばこのような並行処理プログラミングを意識しないでも簡単に実装できてしまうってことね。
TAGS: Java ,NetBeans |
2013年3月14日11:48 PM |
Java NetBeans
先日はシステムプロパティを取得するプログラムを組んでみたけど誰からもツッコミが入らなかったのでこのまま
勝手にイケイケでよくあるサンプルコードを JDK 8 ならこんなになるのかって勝手に思い込む遊びをします。
決して良い子のみんなは真似をしないようにね!
とりかえしのつかないことになるといけないからね(爆
今回は Java 8 について Twitter 上で下記のようなつぶやきがあったのでそれも試してみます。
「みんな、Java8のラムダは飾りでメソッド参照こそ本命ということに気づいてきた」
私は新しく使いやすくなる日付関係の Date and Time API が本命だと気付きました。(^_^;)
これも今回ちょこっとだけ使ってみたいと思います。
開発環境はこの前と同じです。
NetBeans 8 Dev の未来を先取りする賢い補完機能にずいぶん助けられます。
Java 8 を気楽に試してみたい人にはお勧めです。
では、今回試してみたプログラムをご覧ください。
素人が組んだものですから生暖かい眼差しで見て間違ってるところやここはこうしたほうがいいよって優しく教えてくれたら感激です。
jp\yucchi\mylambdasample\MyTeam.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
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 <MyTeam> 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 をさらってご覧になってくださいませ。
カレンダー関係に悩まされてきたそこの あ・な・た !
やっとイライラから解放されるかもしれません。
カレンダーをセットするのも簡単になってます。(50行目)
今まで月の扱いがうざいなぁって思っていたのがやっと解消されますね。
次に、メソッド参照をみてみましょう。
118行目、120行目、128行目、129行目で使ってます。
:: を使った何かしっくりこない違和感の塊がメソッド参照と呼ばれている新機能です。
引数で渡されたオブジェクトのメソッドを呼ぶ機能のようです。
これは単にコード記述量が少なくなるだけなんだろうか?
他に何かメリットがあるのか良く解りません。
今回は static メソッドを使用してますが特定のオブジェクトのインスタンスメソッドや
特定の型の任意のオブジェクトのインスタンスメソッドが使えるようです。
特定のオブジェクトのメソッド参照は、異なる関数型インターフェースに変換する便利な手段を提供します。
< font size = "4" > Callable <path> <Path> c = . . .
PrivilegedAction <path> <Path> a = c :: call ; < / font >
任意のオブジェクトのインスタンスメソッド参照は
< font size = "4" > Arrays . sort ( names , String :: compareToIgnoreCase ) ; < / font >
と引数の数が違います。任意のオブジェクトのメソッド参照には第一引数にインスタンスを渡してます。
要するにラムダ式を書く代わりに既存のメソッドを呼び出すことができるよってことなのかな?
これが Java 8 の本命なのか?
私が知らないもしくは理解が足らないのでもっと便利で素敵な使い方があるのだろうか?
ああ!今日も眠れそうにないなw
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)
では、そろそろ寝ようかな。(眠れたら幸せになれるかも)
TAGS: Java ,NetBeans |
2013年3月14日12:57 AM |