2016-06-22 5 views
1

にマッピングするために収集し、私はJavaの8ストリームでかなり良いなっていたと思ったが、その後...Javaストリームは、複数のキー

私はFooインタフェースを持っていますそれぞれのキーを使用してMap<String, Foo>Stream<Foo>

Map<String, Foo> foosByKey = fooStream.collect(
    Collectors.toMap(Foo::getKey, Function.identity())); 

しかし、私はMap<Bar, Foo>にそれらを収集したい場合は?言い換えれば、スチームの中のFooのそれぞれについて、Foo.bars()によって返されたBarインスタンスのすべてにキーを付けたマップにFooを入れたいと思います。どこから始めますか?

+0

いいえ、あなたはそれを後方に持っています。 'Map 'は、 'Bar'と' Foo'インスタンスの間に1対1のマッピングを暗示します。 'Map 'や 'Map 'を考えてみましょう。人は複数のクレジットカードを持ち、書籍は複数のISBNを持つことができます。ここでは何も複雑ではありません。 –

+0

私はその意味を理解していますが、私はちょっと付帯的な点につきたくありませんでした。マッピングが双方向かどうかは、グラフが方向性を持っているかどうかによって決まります。 Javaの 'Map'は単方向であるため、マップすることはできません--- Guavaには例えばBiMapがあります。 _relationship_は1対1であると言いたいと思います。この場合、_relationship_は多対1です( 'Bar' -'Foo')。しかしもう一度これはポイントのそばで一種のものです---ビールについて議論することです。要約すると、 'Foo'は多くの' Bar'を持つことができ、 'Bar'を' Foo'にマップしたいのです。乾杯! –

+0

確かに、それぞれの 'Foo'が多くの' Bar'を持つことができ、すべての 'Bar'は区別され、よく、私は[Sotiriosの答え](http://stackoverflow.com/a/37956805/2711488)には、適切な解決策が含まれています。あなたが彼の答えを受け入れることを止めさせる何か、私達は対処すべきことはありますか? – Holger

答えて

2

hereが示唆するように、それぞれFooからBarの値を抽出し、それらのペアを作成することをお勧めします。ペアを取得したら、Mapに収集することができます。それは(Javaは単純Pairタイプを持っていない)が利用可能ですので、例えば、

Map<Bar, Foo> map = fooStream.flatMap(foo -> foo.bars().map(bar -> new SimpleEntry<>(bar, foo))) 
      .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); 

は、ここではSimpleEntryを使用しています。より具体的にあなた自身で書くことができます。

+1

'SimpleEntry <>'の使い方は涼しいです---私はJavaが少なくとも "Pair"に似た何かを持っていることを認識していませんでした。私はもう少しコンパクトなものを望んでいましたが、これが私達が得ることのできる最高のものかもしれません。他の選択肢があるかどうかを私は少し待っています。 –

+1

Java 9では、Map.entry(bar、foo)を使用して、値ベースの不変エントリをより簡潔な方法で構築することができます。 – Holger

関連する問題