现在,我有以下代码,该代码采用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种不同的食谱,它应该遍历所有这些食谱,如果发现重复,则将其合并。实现此目标的最佳方法是什么?
答案 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
类实现为equals
和hashcode
,则可以在Set中直接使用它。当然,您在Recipe
中还将有一个方法将所有成分作为List
返回。然后,以下内容将返回所有唯一的成分。
Set<Ingredients> merge(List<Recipe> recipies) {
return recipies.stream().map(s -> s.allIngredients()).collect(Collectors.toSet());
}