使用Java 8流将数据收集到Guava的ListMultiMap中

15
我正在尝试使用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
                )
        );

但是在集合级别,我只能传递一个参数,似乎找不到传递两个参数的方法。根据网站上的示例,我了解到要同时使用两个参数,需要将“pair”存储在multimap中,如下所示:

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

然而这不是我想要的,我想使用Java 8的收集器(而不是forEach)按州名和城市名将数据收集到ListMultimap中。

有人可以帮我吗? 谢谢!


2
该链接后面的代码看起来不太好;原始类型、未经检查的强制转换和累加器不需要的类型变量。 - Jorn Vernee
你是对的!谢谢你指出来!我以为它是正确的,因为我发现很多其他网站都有类似的实现。谢谢! - codastic
2个回答

22

3

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

谢谢!我正在寻找与Louis Wasserman的答案类似的东西,但是你给了我一个非常好的想法,我需要用它做其他事情,你说“你可以创建一个自定义收集器”。 - codastic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接