循环浏览n张地图

时间:2018-12-14 10:15:23

标签: java loops maps

现在,我有以下代码,该代码采用2条配方,并在配方中查找重复项,然后将它们“合并”。

public void mergeIngredients(Recipe recipe1, Recipe recipe2) {

    Map<String, Ingredients> recipe1Map = recipe1.getIngredientsMap();
    Map<String, Ingredients> recipe2Map = recipe2.getIngredientsMap();

    for (Map.Entry<String, Ingredients> s : recipe1Map.entrySet()) {

        if (recipe2Map.containsKey(s.getKey())) {
            double newValue = recipe1.getAmount(s.getKey()) + recipe2.getAmount(s.getKey());
            System.out.println(newValue);
        }
    }
}

我想更改此代码,因此我不仅需要重构代码,还需要重构代码,以便可以提取N张地图并比较所有地图。

示例:用户输入8种不同的食谱,它应该遍历所有这些食谱,如果发现重复,则将其合并。实现此目标的最佳方法是什么?

3 个答案:

答案 0 :(得分:2)

我首先将所有Maps的所有键提取到Set中。这为您提供了所有独特的配料键。

然后迭代该Set并从所有配方中获取所有值并将其合并。

例如:

public void mergeIngredients(Set<Recipe> recipes) {

    Set<String> keys = recipes.stream()         //
            .map(Recipe::getIngredientsMap)     // Get the map
            .flatMap(m -> m.keySet().stream())  // Get all keys and make 1 big stream 
            .collect(Collectors.toSet());       // Collect them to a set

    for (String k : keys)
    {
        double newValue = recipes.stream()       //
                .map(Recipe::getIngredientsMap)  //
                .map(i->i.get(k))                //
                .mapToDouble(i->i.getAmount())   //
                .sum();                          //
        System.out.println(newValue);
    }

}

您可能可以更有效地执行此操作;但这很容易理解。

答案 1 :(得分:0)

如果键重复,则可以使用Merging Multiple Maps Using Java 8 Streams

public void mergerMap() throws Exception {
    Map<String, Integer> m1 = ImmutableMap.of("a", 2, "b", 3);
    Map<String, Integer> m2 = ImmutableMap.of("a", 3, "c", 4);

    Map<String, Integer> mx = Stream.of(m1, m2)
        .map(Map::entrySet)          // converts each map into an entry set
        .flatMap(Collection::stream) // converts each set into an entry stream, then
                                     // "concatenates" it in place of the original set
        .collect(
            Collectors.toMap(        // collects into a map
                Map.Entry::getKey,   // where each entry is based
                Map.Entry::getValue, // on the entries in the stream
                Integer::max         // such that if a value already exist for
                                     // a given key, the max of the old
                                     // and new value is taken
            )
        )
    ;

    Map<String, Integer> expected = ImmutableMap.of("a", 3, "b", 3, "c", 4);
    assertEquals(expected, mx);
}

答案 2 :(得分:0)

我真的没有看到需要您的食材的地图,因此这里是替代解决方案。 如果您将Ingredients类实现为equalshashcode,则可以在Set中直接使用它。当然,您在Recipe中还将有一个方法将所有成分作为List返回。然后,以下内容将返回所有唯一的成分。

Set<Ingredients> merge(List<Recipe> recipies) {
    return recipies.stream().map(s -> s.allIngredients()).collect(Collectors.toSet()); 
}