2016-10-12 8 views
1

ストリームの前のステップの要素にアクセスする良い方法はありますか?ストリーム内の前のステップの要素にアクセスするか、または要素を「パラメータ」として次のステップに渡しますか?

ここでの例は、親(String)のストリームから始まり、各親の2つの子(Integer)へのflatMapsです。 Integerの子(forEach)を処理している段階で、親Stringが何であるかを "覚えている"ことを覚えています( 'parentFromPreviousStep'コンパイルエラー)。

明白な解決策は、StringとIntegerのホルダークラスを導入し、flatMapにそのようなホルダーオブジェクトのストリームを生成することです。しかし、これはちょっと不思議そうです。私は、そのようなチェーンの "前の要素"にアクセスする方法や、(特別なホルダークラスを導入することなく) "パラメータを渡す"方法があるかどうか疑問に思っていました。

List<String> parents = new ArrayList(); 
    parents.add("parentA"); 
    parents.add("parentB"); 
    parents.add("parentC"); 

    parents.stream() 
      .flatMap(parent -> { 
       List<Integer> children = new ArrayList<>(); 
       children.add(1); 
       children.add(2); 
       return children.stream(); 
      }).forEach(child -> System.out.println(child + ", my parent is: ???" + parentFromPreviousStep)); 

背景:これは実際のJavaアプリケーションをデプロイすることなく、アプリケーションのためのJavaScriptのスクリプトコードを提供するために、アイデアをNashornに起こります。これは私の2つのビジネスオブジェクト(ここではStringとIntegerとして簡略化されています)に特別なJavaホルダークラスを導入したくない理由です。 [上記のJavaコードはNashornでもほとんど同じですが、ストリーム関数はJavaScriptではなくJavaです。]

+2

アソシエーションを覚えておきたい場合は、そのアソシエーションを格納するオブジェクトが必要です。それは自然で、避けられない方法です。さて、値の型がJavaのシーンに入るまで。 Apropos "clumsy":あなたは 'flatMap'関数を' parent-> Stream.of(1,2) 'に単純化することができます。私は知っています、それは単なる例ですが、 'List'を作成し、それを埋めるために、単に' Stream'を得るための基本的な仮定を修正する必要があります。新しい専用のホルダークラスを避けたい場合は、2つのオブジェクト/値を保持するために 'AbstractMap.SimpleImmutableEntry'を使うことができます。 – Holger

+0

@Holger:これは実際に私の質問に答えるものです。そして良いヒントをありがとう!私は "Stream.of"と "SimpleImmutableEntry"を知らなかった。 – StaticNoiseLog

答えて

0

子供は親に集約されます.hmm ..キーと値のペアのような匂いがします。 地図!

このようにして試しました。それは働いた。これが役に立つと願っています。

parents.stream() 
      .flatMap(parent -> { 
       List<Integer> children = new ArrayList<>(); 
       children.add(1); 
       children.add(2); 

       Map<String, List<Integer>> stringListMap = new HashMap<String, List<Integer>>(); 
       stringListMap.put(parent, children); 
       return stringListMap.entrySet().stream(); 
      }) 
      .forEach(entry -> { 
       entry.getValue().stream().forEach(val -> System.out.println(val + ", my parent is: ???" + entry.getKey())); 
      }); 
+1

あなたは 'flatMap'の目的を全滅させています。 'List'インスタンスを下流に渡すことは意図していません。 – Holger

+0

'Map > .Entry'オブジェクトをストリームに渡しています。 'flatMap()'の中では、子 'List'を平面化し、いくつかの' map() 'を初期ストリームに作用させます。私は、flatMap()の誤用が何をしているのかと思います。ではない? –

+1

'Stream >>'を返しています。各エントリにはリストが含まれています。あなたはリストを平らにしていません。これは、ターミナルアクションでそのリストにネストされた 'forEach'を実行しているときに、最も明白に認識できます。 – Holger

1

この質問に対するHolgerのコメントは、貴重な情報を提供し、次の解決策につながります。 JDKにSimpleImmutableEntryが存在することで、この状況で私有のホルダークラスを作成することができないという問題が解決されます。 (Holgerが答えを出したので、これはコミュニティのwikiです。)

Stream.of("parentA", "parentB", "parentC") 
.flatMap(parent -> Stream.of(
      new AbstractMap.SimpleImmutableEntry<>(1, parent), 
      new AbstractMap.SimpleImmutableEntry<>(2, parent)) 
).forEach(child -> System.out.println(child.getKey() + ", my parent is: " + child.getValue())); 
関連する問題