当前位置: 首页 > 知识库问答 >
问题:

使用Java lambda从两个映射构建映射

仲孙默
2023-03-14

我有一些代码需要帮助...我正在尝试使用两个地图作为源并同时使用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

但我无法理解

共有3个答案

韩琛
2023-03-14

这项任务可能可以通过一些简单的方法来完成,例如,replaceAll,以便:

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

有很多方法可以实现这一点,下面是一个使用Java9方法Map.entry()Collectors.flatMap()

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()获取每个模型的键。最后,两者都使用收集器。groupingBy()获取结果:

{
  CAR_AND_BIKE: [A1, Q2, X1, X5],
  CAR: [A1, Q2], 
  BIKE: [X1, X5]
}
孙乐逸
2023-03-14

因为你已经在java-8下面标记了这个问题,所以我假设你有Java8,并且不能访问9Java中的平面地图。在java-8中,你可以使用:Collectors.to地图

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]
 类似资料:
  • 我有两个地图,键为整数,值为双倍。 我想创建第三个按键排序的映射,值将是两个映射的双精度列表。 地图1: Map2: 最终地图: 如上所述,如果一个地图中的一个键在另一个地图中丢失,则另一个地图的最终地图中的值应默认为0.00 我可以使用putAll方法将所有键放入第三张地图。但如何按照我的意愿设定这些值呢? 感谢阅读!

  • 我想将我的应用程序迁移到Spring Boot Jar部署。它目前使用没有启动的Spring4。 我在上有一个REST-API侦听器,在上有一个JavaScript-fronten,可以在上访问。 现在我找不到在靴子里做同样的事情的方法。 通过更改属性,我设法在处获得了api监听,但是我没有在处注册第二个servlet来为我的js-frontend服务。我知道jar部署不支持,我还知道Spring

  • 我有两个apache-nifi流。一个来自数据库,另一个来自flowfile。 摘自处理器。: 或者有没有办法使用另一个处理器来做到这一点?

  • 有两个数据帧 输入 df1 df2 映射具有相似列的两个数据帧 从df2获取至少计数为2的匹配列。这里的和与带有2个值的df1匹配 预期产出:

  • 下面是Main中的随机客户端列表 第二类:产品(字符串名称、枚举类别、BigDecimal价格) 目标->预期结果:在类Main中,创建类Shopping的实例,其中属性是具有 的映射,并用随机数据//integer-购买了多少产品 null null