基本
Runnable
インタフェースをラムダの書き方で実装した場合。
Runnable runnable1 = () ->{
System.out.println("lambda!");
};
runnable1.run();
lambda!
Runnable
はご存知の通りrun
メソッドしかない。
戻り値と引数もない。
なので、上記のように、run
メソッドの処理を特にrun
というメソッドを宣言せずに実装できた。
関数型インタフェース 「引数とか戻り値ある場合はどうなる?」
関数型インタフェースという仕組みを使う。
この後のstreamAPIも絡むので、よく使われるであろう3つについてかく。
Function<T,R>
https://docs.oracle.com/javase/jp/8/docs/api/java/util/function/Function.html
T
は引数の型。R
は戻り値の型を指定する。
Function<Integer, String> asterisker = (i) -> { return "*" + i; };
String result = asterisker.apply(10);
System.out.println(result);
*10
上記は10という数字を引数で渡して、アスタリスクの文字列を先頭に足して文字列を返す処理。
引数2つ渡したい!なんて場合は、BiFunction
なんてのもある。
https://docs.oracle.com/javase/jp/8/docs/api/java/util/function/BiFunction.html
BiFunction<Integer, Integer, String> asterisker = (i, i2) -> { return "*" + (i * i2); };
String result = asterisker.apply(10, 2);
System.out.println(result);
*20
Consumer
https://docs.oracle.com/javase/jp/8/docs/api/java/util/function/Consumer.html
T
は引数の型。Function
の戻り値がない版?
Consumer<String> buyer = (goods) -> {
System.out.println(goods + "を購入しました");
};
buyer.accept("おにぎり");
おにぎりを購入しました
Predicate
https://docs.oracle.com/javase/jp/8/docs/api/java/util/function/Predicate.html
T
は引数の型。test
メソッドは評価した結果をbooleanで返してくれる。
Predicate<String> buyer = (goods) -> {
return goods.equals("おにぎり");
};
boolean result = buyer.test("おにぎり");
System.out.println(result);
true
Comparator として使う
関数型インタフェース、そもそもどういう使い方するの?ってところ。。
int[] numbers = {-1, 2, 0, -3, 8};
List<Integer> numbersList = new ArrayList<>();
for(int n : numbers){
numbersList.add(n);
}
前提
まず数字が入ったリストを適当に用意した。この数字の順番をソートしたい。
Collections#sort
の第二引数では、ソートする方法をComparator
で定義することができる。
本題
下記は、Comparator
をラムダで、小さい値→大きい値にソートするように書いた例。
Collections.sort(numbersList, (a, b) -> { return a - b; });
for(Integer n : numbersList) {
System.out.print(n + ",");
}
-3,-1,0,2,8,
streamAPI
まず、リストなどの大元であるCollections
にstream
というメソッドがjava8から追加された。
Stream<E>
を戻り値で返してくれる。
https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/Stream.html
先ほどと同じように、数値型のリストに適当な値を入れておきました。
int[] numbers = {-1, 2, 0, -3, 8};
List<Integer> numbersList = new ArrayList<>();
for(int n : numbers){
numbersList.add(n);
}
forEarch
numbersList.stream().forEach((i) -> {
System.out.print(i + ",");
});
-1,2,0,-3,8,
リストの中身が変数i
に入ってくるので、それをsysoutしているだけのプログラム。
forEarch
はConsumer
を受け取るので、
今回の数値の場合だと、Constumer<Integer>
を受け取っていることになる。
filter
numbersList.stream().filter((i) -> {
return i > 0;
}).forEach((i) -> {
System.out.print(i + ",");
});
2,8,
意味の通り、フィルタリングしてくれる。
filter
はPredicate
を受け取るので、
Predicate
の中で評価してbooleanの値を返しtrueのものだけ抜粋する。
map
numbersList.stream()
.filter((i) -> { return i > 0;})
.map((i) -> {
return "*" + i + "*"; })
.forEach((s) -> {
System.out.print(s + ","); });
*2*,*8*,
map
はFunction
を受け取るので、
Function
の中で受け取った数値を文字列として返している。