問い
2つのInteger
のリストから、
互いの全ての要素の組み合わせから成るPair
のリストを生成せよ。
ex.) [1,2,3], [5,6] -> [(1,5),(1,6),(2,5),(2,6),(3,5),(3.6)]
trial1
なんかmapでいけるかも。
List<Integer> ints1 = Arrays.asList(1,2,3);
List<Integer> ints2 = Arrays.asList(5,6);
ints1.stream()
.map( i -> ints2.stream().map( j -> Pair.of(i,j)))
.collect(toList());
だめ。
List<Stream<Pair<Integer, Integer>>
が返される。
そもそも...
Stream.map関数は、型Function<? super T,? extends R>
を引数にとり、<R> Stream<R>
を返す。
Stream map(Function super T,? extends R> mapper)
ref. Stream.map
なので、入れ子となっているmapは、
Stream<Pair<Integer, Integer>>
を返し、
その戻り値を受けた大元のmapが、
Stream<Stream<Pair<Integer, Integer>>>
を返すようになる。
そして、終端操作により、
List<Stream<Pair<Integer, Integer>>
が最終的に返される。
(終端操作がどのような処理をしているかについては今後...)
そこでflatMap
flatMapを使うことで、
Streamの各値を別のStreamで置き換え、
生成された全てのStreamは、単一のStreamへ集約されるようになる。
ref. Java8 in Action
定義によると、
flatMapへ引数で渡している
Function<? super T,? extends Stream<? extends R>> mapper
の第二引数が、
? extends Stream<? extends R>
となっており、
戻り値は、
Functionの第二引数のStreamを構成する型Rの<R> Stream<R>
となっている。
Stream flatMap(Function super T,? extends Stream extends R>> mapper)
ref. flatMap
以上を踏まえると、以下のようなコードとなる。
ints1.stream()
.flatMap( i -> ints2.stream().map( j -> Pair.of(i,j)))
.collect(toList());
flatMap( i -> ints2.stream().map( j -> Pair.of(i,j)))
によって返される型は、
Stream<Pair<Integer,Intege>>
で、
終端操作により、List<Pair<Integer,Integer>>
が返される。
flatMapを使うことで、
trial1で入れ子となっていたStreamをよしなにしてくれる感じになる ^^;(説明雑)