У меня есть список объектов, как показано ниже. В итоговом списке не должно быть рецептов, если какой-либо ингредиент не использовался до даты. Возможно ли этого достичь с помощью Java Streams.

Я пытался сделать это, как показано ниже, но получал ошибку компиляции. Очень ценю ответ, так как я изо всех сил пытаюсь найти ответ.

List<Recipes> filteredList =
    recipeList.stream().filter(recipes -> recipes.getIngredients().stream().filter(ingredients -> ingredients.getUseBy().before(lunchDate)).collect(Collectors.toList()));
    [
        {
            "id": 1,
            "recipeName": "Pasta",
            "createdDate": "2020-11-22T00:00:00.000+00:00",
            "ingredients": [
                {
                    "ingredientId": 1,
                    "ingredientName": "Shells",
                    "useBy": "2020-11-20",
                    "bestBefore": "2020-11-18"
                },
                {
                    "ingredientId": 2,
                    "ingredientName": "Mozaralla Cheese",
                    "useBy": "2020-12-20",
                    "bestBefore": "2020-11-23"
                }
            ]
        },
        {
            "id": 2,
            "recipeName": "Burger",
            "createdDate": "2020-11-22T00:00:00.000+00:00",
            "ingredients": [
                {
                    "ingredientId": 3,
                    "ingredientName": "Burger Bun",
                    "useBy": "2020-12-20",
                    "bestBefore": "2020-12-23"
                },
                {
                    "ingredientId": 4,
                    "ingredientName": "Beef Pattie",
                    "useBy": "2020-12-20",
                    "bestBefore": "2020-12-23"
                },
                {
                    "ingredientId": 5,
                    "ingredientName": "Tomato",
                    "useBy": "2020-12-20",
                    "bestBefore": "2020-12-23"
                }
            ]
        },
        {
            "id": 3,
            "recipeName": "Chicken Salad",
            "createdDate": "2020-11-22T00:00:00.000+00:00",
            "ingredients": [
                {
                    "ingredientId": 6,
                    "ingredientName": "Salad Mix",
                    "useBy": "2020-12-20",
                    "bestBefore": "2020-11-15"
                },
                {
                    "ingredientId": 7,
                    "ingredientName": "Chicken",
                    "useBy": "2020-12-20",
                    "bestBefore": "2020-12-23"
                }
            ]
        }
    ]
-2
San San 23 Ноя 2020 в 04:04

2 ответа

Лучший ответ

Рабочий пример (без использования JSON) здесь.

Обратите внимание на следующее:

List<Recipe> filteredList = 
    recipes.stream()
           .filter(r -> ! r.getIngredients()
                           .stream()
                           .anyMatch(i -> i.getUseBy().before(lunchDate)))                         
           .collect(Collectors.toList());

Описание каждого рецепта:

  • получить ингредиенты
  • найдите "плохие" ингредиенты с useBy перед lunchDate
  • исключить (с помощью оператора !) рецепт, если есть «плохие» ингредиенты
0
Michael Easter 23 Ноя 2020 в 04:02

Stream().filter() принимает Predicate<T> в качестве параметра и возвращает поток, состоящий из элементов этого потока, которые соответствуют заданному предикату. Ваши требования можно перефразировать так:

List<Recipes> filteredList = recipeList.stream().filter(predicate: recipes does not contain any ingredient past useBy date).collect(Collectors.toList()));

И ваша проблема изменена, чтобы написать предикат, который соответствует: recipes не содержат никаких ингредиентов после даты useBy. (Для любого рецепта подсчитайте ингредиенты, прошедшие дату useBy, счет должен быть 0.)

И вы можете использовать другой stream().filter(predicate: count ingredient after useBy date, and it should be 0)

recipes -> recipes.getIngredients().stream()
    .filter(ingredients -> ingredients.getUseBy().after(lunchDate))
    .collect(Collectors.toList()).size() == 0

Затем добавьте предикат к первому выражению фильтра. Окончательное выражение выглядит так:

List<Recipes> filteredList = recipeList.stream().filter(
    recipes -> recipes.getIngredients().stream()
        .filter(ingredients -> ingredients.getUseBy().after(lunchDate))
        .collect(Collectors.toList()).size() == 0
).collect(Collectors.toList()));
1
John Kugelman 23 Ноя 2020 в 03:43
64961341