基本
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
の中で受け取った数値を文字列として返している。