28788


1対多の親子関係があるようなインスタンスのリスト処理を、従来はネストした`for`文で行っていました。

[code]

    class Parent {
        List <Child> children;
    
        List <Child> getChildren() {
            return children;
        }
    }
    
    class Child {
    }
    
[/code]



[code]

    List <Parent> parents = new ArrayList<>();
    // Parent, Child 生成...
    
    for (Parent p : parents) {
        for (Child c : p.getChildren()) {
            System.out.println(c); // c を使った処理
        }
    }
    
[/code]

上記`for`文を、`Stream`を使用したものに置き換えたいと考えています。  
自分が思いついたものとしては次の2パターンが有るのですが、実行結果はどちらも変わらないように思われました。  
実際には途中の処理順やパフォーマンス等、何か差異があるでしょうか。

また、`Stream`の書き方としてより適切なのはどちら(あるいはどちらでもない)か、というのも知りたいです。  
(バラせるところはバラしたほうが良い、つまりパターン1の方が良いのかな、と漠然と考えているのですが…)

[code]

    // パターン1
    parents.stream().map(Parent::getChildren).flatMap(List::stream)
        .forEach(System.out::println);
    
    // パターン2
    parents.stream().flatMap(p -> p.getChildren().stream())
        .forEach(System.out::println);
    
[/code]


CC BY-SA 3.0
2016-09-09T07:49:06.590
28781
2016-09-23T10:06:57.847
2808
question
java java8 stream
ネストしたコレクションの処理をforループからjava8 streamへ置き換える


> 実際には途中の処理順やパフォーマンス等、何か差異があるでしょうか。

  * 逐次(sequential)ストリームとなっているため、両パターンとも処理順序は同一です。
  * （有意差はないと予想しますが、）パフォーマンス比較は実環境にて計測してください。

> Streamの書き方としてより適切なのはどちら(あるいはどちらでもない)か、というのも知りたいです。

正解のない問いだと思いますが、個人的には パターン2 の方が好ましいと考えます。

  * パターン1: `.map(Parent::getChildren).flatMap(List::stream)`
  * パターン2: `.flatMap(p -> p.getChildren().stream())`

論理的には「子Listのflatten処理」でひとかたまりの操作ですから、パターン1のように外側ストリームのメソッドチェインで分断してしまうより、パターン2のように一度のflatMap操作で変換する方が意図をより直接的にコード化しているという考え方です。


CC BY-SA 3.0
2016-09-09T16:09:20.010
28788
2016-09-09T16:09:20.010
49
28781
answer


どちらでもいいのではないでしょうか？  
こういう書き方もあります。

[code]

    parents.stream()
        .forEach(p -> p.children.stream()
            .forEach(System.out::println));
    
[/code]

Parentが変わる前後で何か処理をしたい場合はこの書き方がいいですね。


CC BY-SA 3.0
2016-09-23T04:01:01.413
29068
2016-09-23T10:06:57.847
2016-09-23T10:06:57.847
28781
answer