Java8でラムダしてみる。
概要
今まで何となく追加されたんだなぁと思いつつ触ってなかったのでこの機会に「ラムダ式」を触ってみます。
ラムダ式って?
ラムダ式(wikiより)…計算模型のひとつで、計算の実行を関数への引数の評価(英語: evaluation)と適用(英語: application)としてモデル化・抽象化した計算体系である。
何のこっちゃ判らん。。。
しっくり来たサイトから引用**「関数型インタフェース」のメソッドを実装する際に式として使う事が出来る。**との事、最近よく聞く関数型プログラミングというやつらしい
関数型インタフェース…抽象メソッドを一つ持つインターフェース
こんなの
@FunctionalInterface
interface Hello{
public void sayHi(String name);
}
ざっくりいうと、以下なのかな
- コーディングをシンプルに記述できる
- 簡単に並列処理を組める
- ラムダ式が前提の新機能が多いので、覚えるしかない
試してみる(本題)
本当にシンプルに処理が記述できるのか?並列処理を楽に組めるの?どの位早いの?を実際に体験してみようと思い、今まで逃げてきたラムダ式を書いてみました。
今回のお題
大量のオブジェクト配列の中から、特定のデータがセットされている件数を数える。
まずは大量の配列を用意
まずは、staticイニシャライザでPersonクラスのリストを沢山作ります。
Personクラスは、名前、税別、年齢を持っています。
private static List<Person> list;
static {
list = new ArrayList<Person>();
Random rnd = new Random();
while(list.size() != 50000000){
int age = rnd.nextInt(100);
boolean isMan = false;
if (age%2 == 0) {
isMan = true;
}
String name = "name_" + age;
list.add(new Person(name, isMan, age));
}
}
Java7(泥臭く)
とりあえず、ループしながら女性だけの数を数えます。
public long countFor7(){
long count = 0;
for (Person person : list) {
if (person.isMan() == false) {
count++;
}
}
return count;
}
Java8(ラムダ)
おお、確かに短い
public long countFor8(){
return list.parallelStream().filter(p -> p.isMan() == false).Count();
}
良くあるサンプルですが、他にはsortとかfirstとか色々あります。
これが、提供された便利なAPIってやつですね、、、
本当は自分で関数インタフェース作ろうと思ったんだけど、挫折…
本気でラムダ覚えようと思ったら、もっと色々勉強しないと判らない事が判った。
尚、今回一番苦労したのは、大量データによるOutOfMemoryを回避する為
実行環境を探したり設定変えたりだったりする。
動かしてみる
static イニシャライザは別として計測
スペック
- Core i7
- 8G Memory
- SSD 128G
java7で実行!!
count is 9999968!!
135 msec
java8で実行!!
count is 9999968!!
186 msec
さすが並列処理のおかげで遅くな・っ・て・い・る??
5,6回やって、大体同じような結果
考察
どうやら以下の制約があるらしい
少ないデータだったり、データ操作の種類によっては並列化の恩恵は得られない、むしろ、オーバーヘッドが増えて遅くなる。
まあ、そうですよね
次回
もうちょっと調べて、ちゃんと並列処理で早くなるサンプルを作ります。