web-dev-qa-db-ja.com

Java 8ストリームを使用してGuavaのListMultiMapに収集します

ForEach操作を使用せずにJava 8を使用してListMultiMapに収集しようとしています。

私がJava 7でコードを書くとしたら、次のようになります。

ListMultimap<String, String> result = ArrayListMultimap.create();
     for(State state: states) {
      for(City city: state.getCities()) {
        result.put(state.getName(), city.getName());
      }
    }

このようなシナリオで使用する独自のコレクターの作成について説明している website をオンラインで見つけました。私はこの実装をコレクターに使用しました。次に、次のコードを記述しました。

     ListMultimap<String, String> result = states
        .stream()
        .flatMap(state -> state.getCities().stream()
            .map(city -> {
              return new Pair(state, city);
            }))
        .map(pair -> {
          return new Pair(pair.first().getName(), pair.second().getName()));
        })
        .collect(MultiMapCollectors.listMultimap(
                    Pair::first,
                    Pair::second
                )
        );

しかし、収集レベルでは、パラメーターを1つだけ渡すことができ、2つのパラメーターを渡す方法を見つけることができます。ウェブサイトの例に従って、両方を使用するには、次のようなマルチマップに「ペア」を格納する必要があることを理解しました。

ArrayListMultimap<String, Pair> testMap = testObjectList.stream().collect(MultiMapCollectors.listMultimap((Pair p) -> p.first().getName()));

ただし、これは私が探しているものではありません。Java 8のコレクター(およびforEachなし))を使用して、州の名前と都市の名前を使用してListMultimapに収集します。

誰かが私を助けてくれますか?ありがとうございました!

15
codastic

ImmutableListMultimap.flatteningToImmutableListMultimap

return states.stream()
   .collect(flatteningToImmutableListMultimap(
      State::getName,
      state -> state.getCities().stream().map(City::getName)));
18
Louis Wasserman

あなたcouldそのためのカスタムコレクターを作成します(Louis Wassermanの答えは内部でforEachOrderedを実行することに注意してください。内部または外部でforEachを実際にエスケープすることはできません)。

 ListMultimap<String, String> list = states.collect(Collector.of(ArrayListMultimap::create, (multimap, s) -> {
        multimap.putAll(s.getName(), s.getCities().stream().map(City::getName).collect(Collectors.toList()));
    }, (multi1, multi2) -> {
        multi1.putAll(multi2);
        return multi1;
    })); 
2
Eugene