2016-01-11 20 views
11

私はMap<A, Map<B, C>>を持っており、Javaストリームを使用してMap<B, List<C>>を取得したいと考えています。Javaストリーム:内部マップキーでグループ化された値を取得

私は次のようにそれをやろう:私は何を期待

public <A, B, C> Map<B, List<C>> groupsByInnerKey(Map<A, Map<B, C>> input) { 
    return input.values() 
      .stream() 
      .flatMap(it -> it.entrySet().stream()) 
      .collect(Collectors.groupingBy(Map.Entry::getKey)); 
} 

  • flatMapは、Map.Entry<B, C>
  • collect(Collectors.groupingBy(...))StreamMap.Entry<B, C>に適用され、Bを返している機能を取りいますしたがって、Cの値をList<C>に収集します。

しかし、それは文字通り、コンパイルされません。

非静的メソッドは、最後の行でMap.Entry::getKey

静的コンテキストから参照することはできません。

誰かが何が間違っているのか、自分が望むことを達成するための正しい方法は何かを説明できますか?

+0

可能な重複:http://stackoverflow.com/questions/29373026/how-to-get-all-values-from-the-inner-maps-of-a-map-using-a-common -key –

+0

@ ShiladittyaChakraborty、実際には、私はこれをする期待された方法がうまくいかない理由について尋ねています。また、タスクは参照した質問とは少し異なります。 – hotkey

答えて

11

しかし、あなたが収集したいしたい、実際のエントリの値は次のとおりです。

Map<B, List<C>>は、あなたが Map.Entry<B,C> Cにマップする mappingを追加する必要があるものを手に入れるために、 、エントリ自体ではありません。現在のコードでは、 Map<B, List<Map.Entry<B, C>>>が得られます。

このように、Collectors.mappingへの呼び出しが欠落しています。このコレクタは、Stream要素を指定されたマッパー関数にマップし、その結果を下流のコンテナに収集します。この場合、マッパーはMap.Entry::getValue(マップエントリから値を戻す)で、ダウンストリームコレクタはListに集まります。

public <A, B, C> Map<B, List<C>> groupsByInnerKey(Map<A, Map<B, C>> input) { 
    return input.values() 
      .stream() 
      .flatMap(it -> it.entrySet().stream()) 
      .collect(Collectors.groupingBy(
       Map.Entry::getKey, 
       Collectors.mapping(Map.Entry::getValue, Collectors.toList()) 
      )); 
} 
+1

ありがとう、それは働いた。だから、私は実際にコンパイラのエラーメッセージで混乱していました。これは、型の不一致に関するものであり、非静的な文脈に関するものではありません。 :) – hotkey

7

ストリームパイプラインはMap<B, List<Map.Entry<B,C>>>で、Map<B, List<C>>ではありません。あなたのストリームはMap.Entryオブジェクトで構成されている

return input.entrySet() 
     .stream() 
     .flatMap(it -> it.getValue().entrySet().stream()) 
     .collect(Collectors.groupingBy(Map.Entry::getKey,Collectors.mapping(Map.Entry::getValue,Collectors.toList()))); 
関連する問題