18

Google Places API から取得した Google PlaceSummary オブジェクトのリストがあります。Google プレイス ID でそれらを収集してグループ化したいのですが、要素の順序も保持します。私がうまくいくと思ったのは次のとおりです。

Map<String, List<PlaceSummary>> placesGroupedByPlaceId =
            places.stream()
                  .collect(Collectors.groupingBy(
                          PlaceSummary::getPlaceId,
                          LinkedHashMap::new,
                          Collectors.mapping(PlaceSummary::getPlaceId, toList())
                  ));

しかし、それはコンパイルさえしません。Collectorsの Java API ドキュメントによると、そうあるべきだと思われます。

以前、私はこのコードを持っていました:

    Map<String, List<PlaceSummary>> placesGroupedByPlaceId = places.stream()
            .collect(Collectors.groupingBy(PlaceSummary::getPlaceId));

ただし、Streams API の標準.collect()では、後続の要素の順序は保持されませんHashMap(明らかに、HashMaps は順序付けされていないため)。LinkedHashMapMap が各バケットの挿入順序でソートされるように、出力を にしたいと思います。

ただし、私が提案した解決策はコンパイルされません。まず、それはPlaceSummary::getPlaceId関数ではないと言っているため、認識しません-関数であることはわかっていますが。次に、M に変換できないと表示LinkedHashMap<Object, Object>されます。M は一般的なコレクションであると想定されているため、受け入れられる必要があります。

LinkedHashMapJava Stream API を使用して List を に変換するにはどうすればよいですか? それを行うための簡潔な方法はありますか?理解するのが難しすぎる場合は、古い学校の Java 8 より前のメソッドに頼ることができます。

List を LinkedHashMap に変換する際に別のスタック オーバーフローの回答があることに気付きましたが、具体的に繰り返し処理しているオブジェクトを「これ」で収集する必要があるため、これには必要な解決策がありません。

4

4 に答える 4

21

あなたは本当にあなたが望むものに近づいています:

Map<String, List<PlaceSummary>> placesGroupedByPlaceId =
            places.stream()
                  .collect(Collectors.groupingBy(
                          PlaceSummary::getPlaceId,
                          LinkedHashMap::new,
                          Collectors.mapping(Function.identity(), Collectors.toList())
                  ));

このメソッドでは、場所 ID ではなく、インスタンスをCollectors.mapping指定する必要があります。PlaceSummary上記のコードでは、次のように使用Function.identity()しました: このコレクターは値を構築するために使用されるため、(ID ではなく) 場所自体を蓄積する必要があります。

Collectors.toList()の代わりに直接書き込むことができることに注意してくださいCollectors.mapping(Function.identity(), Collectors.toList())

これまでのコードは、実際には を作成しているため、コンパイルされませんMap<String, List<String>>。各 ID の ID を蓄積しています (これは非常に奇妙です)。


これをジェネリックメソッドとして書くことができます:

private static <K, V> Map<K, List<V>> groupByOrdered(List<V> list, Function<V, K> keyFunction) {
    return list.stream()
                .collect(Collectors.groupingBy(
                    keyFunction,
                    LinkedHashMap::new,
                    Collectors.toList()
                ));
}

次のように使用します。

Map<String, List<PlaceSummary>> placesGroupedById = groupByOrdered(places, PlaceSummary::getPlaceId);
于 2015-10-15T13:50:37.467 に答える
4

ファイナルコレクターについて少し混乱したと思います。各マップ値に必要なものを表すだけです。mapping元のオブジェクトのリストが必要なだけなので、セカンダリ コレクターは必要ありません。

    Map<String, List<PlaceSummary>> placesGroupedByPlaceId =
          places.stream()
                .collect(Collectors.groupingBy(PlaceSummary::getPlaceId,
                                               LinkedHashMap::new,
                                               Collectors.toList()));
于 2015-10-15T14:01:32.880 に答える