実装したかったこと
Listの要素のクラスから2つのString
を抽出し、
その2つのString
を格納したPairのListを生成する。
Stream使えばいけそう^^
ビルドできない
List<Hogehoge> list;
list
.stream()
.map(Pair.of(Hogehoge::getFoo, Hogehoge::getBar))
// ↑↑ Object is not a functional interface ↑↑
.collect(Collectors.toList())
ん!?
Functional Interface !?
関数型インタフェースは、
関数メソッドと呼ばれる単一の抽象メソッドが含まれているインターフェース
ref . パッケージjava.util.function
ref . Java8 in Action
加えて...
ラムダ式を使うことで、
関数型インターフェースの抽象メソッドの実装をインラインで明示でき、
その全体式を関数型インターフェースのインスタンスとして扱うことができる。
(つまるところ、関数型インターフェースの実装となる)
ref . Java8 in Action
なるほど。
ここで、以下の2つのことを理解。
- 関数型インターフェースは、単一の抽象メソッドが含まれているインターフェース
- ラムダ式により、関数型インターフェースを実装可能
そもそもStream.map()の定義って ^^;
Stream map(Function super T,? extends R> mapper)
パラメータ: mapper
- 各要素に適用する非干渉でステートレスな関数
引数mapperの型であるFunctionは、
単一抽象メソッドapply
を持つ「関数型インターフェース」
ref. Interface Function<T,R>
本題に戻って
関数型インターフェースであるFunctionをラムダ式で実装して、
mapに渡せばよいことがわかった。
List<Hogehoge> list;
Function<Hogehoge,Pair<String,String>> makePairsFromObj =
hoge -> Pair.of(hoge.getFoo(), hoge.getBar());
List<Pair<String, String>> pList = list
.stream()
//.map(makePairFromObj::apply)
.map(makePairFromObj) // Function型の変数を渡せばよい by @swordone
.collect(Collectors.toList());
もしくは、直接ラムダ式を渡す(@swordoneさんからの指摘)
List<Hogehoge> list;
List<Pair<String, String>> pList = list
.stream()
.map(hoge -> Pair.of(hoge.getFoo(), hoge.getBar()))
.collect(Collectors.toList());
\(^o^)/