简体   繁体   English

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

[英]Collect into Guava's ListMultiMap using Java 8 streams

I am trying to collect into a ListMultiMap using java 8 without using the forEach operation. 我试图使用java 8收集到ListMultiMap而不使用forEach操作。

If I were to write the code in Java 7, it will be something like this: 如果我在Java 7中编写代码,它将是这样的:

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

I found online a website that talks about creating your own collectors to use in scenarios such as this one. 我在网上找到了一个网站 ,讨论如何创建自己的收藏家,以便在这样的场景中使用。 I used this implementation for the collector. 我将此实现用于收集器。 I then wrote the following code: 然后我写了下面的代码:

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

But at the collect level, I can only pass just one parameter, and I can seem to find a way to pass two parameters. 但在收集级别,我只能传递一个参数,我似乎找到了传递两个参数的方法。 Following the example from the website, I understood that to use both, I need to store a "pair" in the multimap such as the following: 按照网站上的例子,我明白要使用两者,我需要在多图中存储一对“对”,如下所示:

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

However this is not what I'm looking for, I want to collect into ListMultimap using the state's name and the city's name using java 8's collector (and no forEach). 然而,这不是我想要的,我想使用状态的名称和使用java 8的收集器(并且没有forEach)的城市名称收集到ListMultimap中。

Can someone help me with that ? 有人可以帮助我吗? Thank you! 谢谢!

ImmutableListMultimap.flatteningToImmutableListMultimap

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

You could create a custom collector for that (note that Louis Wasserman's answer will do a forEachOrdered internally, you can't really escape a forEach either internally or externally). 可以为此创建一个自定义收集器(请注意,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;
    })); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM