【问题标题】:Using Java lambda to build map from two maps使用 Java lambda 从两个地图构建地图
【发布时间】:2019-08-21 15:25:13
【问题描述】:

我有一些代码需要帮助...我正在尝试使用两个地图作为源并同时使用 java lambdas 构建地图

Map<String, List<String>> motorsMapping = new HashMap<>();

motorsMapping.put("CAR", Collections.singletonList("AUDI"));
motorsMapping.put("CAR_AND_BIKE", Arrays.asList("AUDI", "BMW"));
motorsMapping.put("BIKE", Collections.singletonList("BMW"));

Map<String, List<String>> models = new HashMap<>();
models.put("AUDI", Arrays.asList("A1", "Q2"));
models.put("BMW", Arrays.asList("X1", "X5"));


motorsMapping.keySet().forEach(key -> {
     Map<String, List<String>> result = new HashMap<>();
     result.put(key, new ArrayList<>());
     motorsMapping.get(key).forEach(value -> models.getOrDefault(value, Collections.emptyList()).forEach(property -> result.get(key).add(property)));
});

我可以使用您在上面看到的 foreach 来做到这一点,但我试图使用 lambdas 来做到这一点......像这样

Map<String, List<String>> collected = motorsMapping
    .entrySet()
    .stream()
    .map(entry -> {
        return entry.getValue()
            .stream()
            .map(key -> models.getOrDefault(key, Collections.emptyList()))
            .flatMap(List::stream)
            .collect(Collectors.groupingBy(entry.getKey(), Collectors.toList()));
    }
)...

我想要的输出是这样的

CAR -> A1, Q2
BIKE -> X1, X5
CAR_AND_BIKE -> A1, Q2, X1, X5

但我无法理解它

【问题讨论】:

    标签: java lambda java-8 java-stream collectors


    【解决方案1】:

    当您在java-8 下标记了这个问题时,我假设您拥有 Java 8 并且无法访问 Java 9 中的flatMapping。在java-8 中,您可以使用 :Collectors.toMap

    Map< String, List< String > > collected = motorsMapping.entrySet( )
                .stream( )
                .collect( Collectors.toMap( Map.Entry::getKey
                        , motorMap -> motorMap.getValue( )
                                        .stream( )
                                        .flatMap( value -> models.get( value ).stream( ) )
                                        .collect( Collectors.toList( ) ) ) );
    collected.entrySet( ).stream( ).forEach( System.out::println );
    

    这是输出:

    CAR_AND_BIKE=[A1, Q2, X1, X5]
    CAR=[A1, Q2]
    BIKE=[X1, X5]
    

    【讨论】:

      【解决方案2】:

      有很多方法可以实现这一点。这是使用 Java 9 方法 Map.entry()Collectors.flatMapping() 的一个:

      Map<String, List<String>> collected = motorsMapping.entrySet().stream()
              .flatMap(e -> e.getValue().stream()
                      .map(i -> Map.entry(e.getKey(), models.get(i).stream())))
              .collect(Collectors.groupingBy(Map.Entry::getKey, 
                      Collectors.flatMapping(Map.Entry::getValue, Collectors.toList())));
      

      如果您仅限于 Java 8,则可以使用此方法:

      Map<String, List<String>> collected = motorsMapping.entrySet().stream()
              .flatMap(e -> e.getValue().stream().flatMap(i -> models.get(i).stream())
                      .map(i -> new AbstractMap.SimpleEntry<>(e.getKey(), i)))
              .collect(Collectors.groupingBy(Map.Entry::getKey,
                      Collectors.mapping(Map.Entry::getValue, Collectors.toList())));
      

      最后一个使用AbstractMap.SimpleEntry()而不是Map.entry()

      两种解决方案都使用flatMap() 来获取每个键的模型列表。之后再次使用flatMap() 来获取每个模型的密钥。最后都使用Collectors.groupingBy() 得到结果:

      {
        CAR_AND_BIKE: [A1, Q2, X1, X5],
        CAR: [A1, Q2], 
        BIKE: [X1, X5]
      }
      

      【讨论】:

        【解决方案3】:

        这个任务可以通过像replaceAll 这样简单的东西来完成:

        Map<String, List<String>> result = motorsMapping;
        result.replaceAll((vehicle, categories) -> categories.stream()
                .flatMap(category -> models.getOrDefault(category, Collections.emptyList()).stream())
                .collect(Collectors.toList()));
        

        【讨论】:

          猜你喜欢
          • 2022-11-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-03-02
          • 2011-06-24
          • 1970-01-01
          • 2020-03-30
          • 1970-01-01
          相关资源
          最近更新 更多