使用Java 8流收集到番石榴的ListMultiMap中

2022-09-03 13:08:54

我正在尝试使用java 8收集到ListMultiMap中,而不使用forEach操作。

如果我用Java 7编写代码,它将是这样的:

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

我在网上找到了一个网站,该网站讨论了如何创建自己的收集器以在诸如此类的场景中使用。我将此实现用于收集器。然后我写了下面的代码:

     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
                )
        );

但是在集合级别,我只能传递一个参数,并且我似乎可以找到一种传递两个参数的方法。按照网站的例子,我明白要同时使用两者,我需要在多地图中存储一个“对”,如下所示:

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

然而,这不是我想要的,我想使用州名收集到ListMultimap中,并使用java 8的收集器(而不是forEach)的城市名称。

有人可以帮我吗?谢谢!


答案 1

ImmutableListMultimap.flatteningToImmutableListMultimap

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

答案 2

你可以为此创建一个自定义收集器(请注意,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;
    })); 

推荐