目的
Lambda、Stream、LocalDateの使い方をマスターして普段から使えるようになろう!
Lambda
Lambdaとは?
Lambdaはメソッドを変数として定義して使用する方法です。
Lambdaを使うとコード行を少なく記述することができます。
また、定義したメソッドを他のメソッドの引数に渡すこともできます。
数回しか使わなく他のクラスから参照しないメソッドはLambdaで書くようにしましょう!
基本的な書き方
Lambdaはオーバーライドする関数名などを全て省略して書くため、メソッドが1つしか定義されていないインターフェースを継承する必要があります。
Javaにはすでに引数や戻り値の数に応じて使える関数型インターフェースを用意してくれているのでそれらを使います。
※注意 引数と戻り値にintやdoubleといったプリミティブ型を使用するときはそれぞれ対応しているインターフェースを使いましょう! (パフォーマンスに差が出てくるので)
例)
// intを送ってintを受け取りたい時
Function → IntUnaryOperator
インターフェースの詳しい種類は以下に載っています。
http://www.ne.jp/asahi/hishidama/home/tech/java/functionalinterface.html#h_Function
引数戻り値あり、Function
引数の型、戻り値の型というように定義します。
実行はapply()
メソッドを使います。
2つの引数を受け取れるBiFunctionというものもあります。
引数と戻り値にint型を指定したい場合はFunctionではなくIntUnaryOperator
を使います。
実行メソッドはapplyAsInt()
です。
import java.util.function.*;
// main内
Function<String, String> f = (i) -> { return i +"OK"; };
System.out.println(f.apply("test")); // testOK
引数のみあり、Consumer
引数の型を指定します。
実行はaccept()
メソッドを使います。
引数をint型に指定したい場合はIntConsumer
を使います。
import java.util.function.*;
// main内
Consumer<String> c = i -> { System.out.println(i); };
c.accept("testOK"); // testOK
戻り値のみあり、Supplier
戻り値の型を指定します。
実行はget()
メソッドを使います。
戻り値をint型に指定したい場合はIntSupplier
を使います。
実行メソッドはgetAsInt()
です。
import java.util.function.*;
// main内
Supplier<String> s = () -> { return "testOK"; };
System.out.println(s.get()); // testOK
引数を受け取って真偽値を返す、Predicate
実行はtest()
メソッドを使います。
FunctionのBoolean指定とPredicateの違いは、FunctionではBooleanが返ってくるのに対し,Predicateではプリミティブ型であるbooleanが返ってきます。
引数をint型に指定したい場合はIntPredicate
を使います。
import java.util.function.*;
// main内
Predicate<String> p = (i) -> { return i.equals("AAA"); };
System.out.println(p.test("AAA")); // true
Stream
Streamとは
List型のfor分などを簡潔に書くことができます。
また、メソッドの引数にLambdaを使うことができます。
使うときはjava.util.stream
をインポートしてきます。
まず、普通のfor分を考えてみます。
for(int i; i < 10; i++){
System.out.println(i+"回目です");
}
これをStreamで書くと
IntStream.range(0, 10).forEach(i -> System.out.println(i+"回目です"));
となり簡潔になります。
また、ArrayListの要素に対してforを回したい場合、
// 変数listに対して
list.stream().forEach(i -> [処理])
というように書くことができます。
中間操作と終端操作
streamには各要素の変換などを行う中間操作メソッドと最終的に値を返したり格納したりする終端操作メソッドがあるます。
終端操作を行わないと変換などをした各要素は保存されないので注意してください。
中間操作は以下のようなものがあります。
.skip(n)
... 最初のn個の要素を捨てる。
.limit(n)
... 最初のn個のみ取り出す。
.filter(i -> [条件])
... 条件に合うものを取り出す。
.distinct()
... 重複を取り除く。
.sorted()
... 自然順序でソートする。カッコ内にソート規則を指定することも可能。
.map(i -> [処理])
... 全ての要素に処理を行う。
終端操作は以下のようなものがあります。
.forEach(i -> [処理])
... 出力する。
.findFirst()
... 始めの要素を返す。
.collect()
... 結果を作成する。(引数によって処理が変わる。)
.count()
... 要素数を返す。
.allMach([条件]) .anyMach([条件]) . noneMach([条件])
... マッチしているか判定する。
LocalDate
LocalDateとは
日付の処理を行うクラスです。
今まで使っていたCalendarクラスよりも扱いやすくなりました。
java.time.LocalDate
をインポートして使います。
以下でよく使う操作を上げていきます。
現在の日付取得
LocalDate date = LocalDate.now();
日付セット
2020-01-01をセット
localDate date = LocalDate.of(2020, 1, 1);
Calendarと違い、Monthを-1しなくていい!
文字列から日付セット
java.time.format.DateTimeFormatterをインポートする。
date = LocalDate.parse("20200101",DateTimeFormater.ofPattern("yyyyMMdd"));
下でも可能
date = LocalDate.parse("2020-01-01");
日付取得
年
date.getYear();
月
date.getMonth();
日
date.getDayOfMonth();
曜日
date.getDayOfWeek();
加減算
+10日
date.plusDays(10);
-10日
date.miusDays(10);
+2年
date.plusYears(2);
日付同士の差
java.time.temporal.ChronoUnitをインポートする。
日にちの差
long diff = ChronoUnit.DAYS.between(date1, date2);
参考資料
Lambda
http://www.ne.jp/asahi/hishidama/home/tech/java/functionalinterface.html#h_Function
https://qiita.com/sano1202/items/64593e8e981e8d6439d3
Stream
http://www.ne.jp/asahi/hishidama/home/tech/java/stream.html
https://qiita.com/kumazo/items/0876c5b251ecc131c960
https://qiita.com/kumazo/items/104fa685da8705b8cfd8
https://qiita.com/kumazo/items/284098c530fceb05805c
LocalDate
https://blog.y-yuki.net/entry/2016/09/15/003000)
https://m-shige1979.hatenablog.com/entry/2017/03/10/080000