Перебрать n карт - PullRequest
       3

Перебрать n карт

0 голосов
/ 14 декабря 2018

Прямо сейчас у меня есть следующий код, который берет 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);
        }
    }
}

Я хочу изменить этот код, поэтому вместочтобы иметь возможность сравнивать только 2 карты друг с другом, мне нужно провести рефакторинг кода, чтобы он мог взять N карт и сравнить их все.

Пример: Пользовательский ввод 8различные рецепты, он должен пройтись по всем этим и объединить ингредиенты, если найдены дубликаты.Каков наилучший способ добиться этого?

Ответы [ 3 ]

0 голосов
/ 14 декабря 2018

Вы можете использовать Объединение нескольких карт с использованием потоков Java 8 в случае дублирования ключей:

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);
}
0 голосов
/ 14 декабря 2018

Я действительно не вижу необходимости в карте для ваших ингредиентов, так что вот альтернативное решение.Если вы делаете класс Ingredients реализующим equals & hashcode, вы можете использовать его непосредственно в наборе.У вас, конечно, также будет метод в Recipe, который возвращает все ингредиенты как List.Затем следующее вернет все уникальные ингредиенты.

Set<Ingredients> merge(List<Recipe> recipies) {
    return recipies.stream().map(s -> s.allIngredients()).collect(Collectors.toSet()); 
}
0 голосов
/ 14 декабря 2018

Сначала я извлеку все ключи из всех Maps в 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);
    }

}

Вы, вероятно, можете сделать это более эффективным;но за этим легче следовать, я думаю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...