任意の検査をして Function<T, R> を実行する。
これは、stream か、Optional で filter 実行後に map あるいは flatMap を実行と
ラムダ式を連結して記述すれば済むことではある。
例)日付文字列→LocalDate
String str; // TODO 日付文字列をstr に格納
LocalDate dt = Optional.ofNullable(str) .filter(e->Pattern.compile("^\\d{4}/(0[1-9]|1[012])/(0[1-9]|[12][0-9]|3[01])$") .matcher(e).matches()) .map(e->LocalDate.parse(e, DateTimeFormatter.ofPattern("yyyy/MM/dd"))) .orElse(LocalDate.of(2021, 4, 1));
Predicate 結果、成功なら処理をする Function<T, R> としてまとめたらどうであろう。
import java.io.Serializable; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; /** * PredicateFunction */ @FunctionalInterface public interface PredicateFunction<T, R> extends Serializable{ R apply(T t); static <T, R> Function<T, R> of(Predicate<T> p, PredicateFunction<T, R> f){ return t-> p.test(t) ? f.apply(t) : null; } static <T, R> Function<T, R> of(Predicate<T> p, PredicateFunction<T, R> f, R r){ return t-> p.test(t) ? f.apply(t) : r; } static <T, R> Function<T, R> of(Predicate<T> p, PredicateFunction<T, R> f, Supplier<R> s){ return t-> p.test(t) ? f.apply(t) : s.get(); } }
Optional の実行で、filter を書かずに当てはめてみる。
Function<String, LocalDate> predicFunction = PredicateFunction.of( t->Pattern.compile("^\\d{4}/(0[1-9]|1[012])/(0[1-9]|[12][0-9]|3[01])$") .matcher(t.toString()).matches() , e->LocalDate.parse(e.toString(), DateTimeFormatter.ofPattern("yyyy/MM/dd")) ); LocalDate date = Optional.ofNullable(str).map(predicFunction) .orElse(LocalDate.of(2021, 4, 1));
今回の例は、Pattern の matcher メソッドが、CharSequenceを引数であるため、
Optional による null チェックが入り、Object の toString() を実行しているのでこのようになっている、
だから、Optional でなく、PredicateFunction の apply メソッド実行で書けば、、、
LocalDate date = PredicateFunction.of( t->Pattern.compile("^\\d{4}/(0[1-9]|1[012])/(0[1-9]|[12][0-9]|3[01])$") .matcher(t==null ? "" :t.toString()).matches() , e->LocalDate.parse(e.toString(), DateTimeFormatter.ofPattern("yyyy/MM/dd")) , LocalDate.of(2021, 4, 1) ).apply(str);
PredicateFunction.of による Function<T, R> を予め生成しておく方法としては
少しばかり有効な手段かもしれない。