Java
このところ Java 8 で注目の Lambda を NetBeans 8 Dev を使ってネットから情報収集して楽しんでます。
今回は絶対はまりそうなコードを紹介します。
Lambda に興味がある人は既にご存じかと思いますが、なかなか面白そうなのでよかったら見てください。
では次のプログラムを実行したらどうなるでしょうか?
jp\yucchi\mylambda_2\MyLambda_2.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
package jp . yucchi . mylambda_2 ;
import java . util . ArrayList ;
import java . util . HashSet ;
import java . util . List ;
import java . util . Map ;
import java . util . Spliterator ;
import java . util . concurrent . ConcurrentHashMap ;
public class MyLambda_2 {
private final static int WOW = 1_000 ;
public static void main ( String . . . args ) {
Map < Integer , Integer > m = new ConcurrentHashMap <> ( ) ;
for ( int i = 0 ; i < WOW ; i ++ ) m . put ( i , i ) ;
List <Integer> root = new ArrayList <> ( ) ;
m . keySet ( ) . spliterator ( ) . forEach ( root :: add ) ;
List <Integer> _root = new ArrayList <> ( ) ;
Spliterator <Integer> right = m . keySet ( ) . spliterator ( ) ;
Spliterator <Integer> left = right . trySplit ( ) ;
left . forEach ( _root :: add ) ;
right . forEach ( _root :: add ) ;
System . out . println ( _root . size ( ) == root . size ( ) ) ;
System . out . println ( _root . equals ( root ) ) ;
System . out . println ( new HashSet ( root ) . equals ( new HashSet ( _root ) ) ) ;
}
}
簡単じゃないかと思ったあなた!
正解です。(^_^)
私のコンピュータでの実行結果は次のようになります。
run: true true true BUILD SUCCESSFUL (total time: 0 seconds)
では、このプログラムの WOW 定数をもっと大きな値にしてみたらどうなるでしょうか?
11 private final static int WOW = 10_000;
それでは実行してみます。
run: true false true BUILD SUCCESSFUL (total time: 0 seconds)
とても素敵な結果が表示されました。(;゜ロ゜)
たぶん、感の鋭い方なら 25 行目のコードをみただけでこのような結果になるのは容易に想像できたでしょう。
これって絶対はまりそうな気がするのは私だけでしょうか?
TAGS: Java |
2013年3月20日5:54 AM |
Java NetBeans
今回は その2 で作ったプログラムの年齢とバストサイズでフィルタリングし、ファイティングパワーで昇順ソートして生成した List を操作してみます。
といっても何も大したことはしていません。
とりあえず下記コードを追加しました。
jp\yucchi\mylambdasample\MyLambdaSample.java
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
// 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 <Integer> 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]
TAGS: Java ,NetBeans |
2013年3月19日7:49 PM |
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 |