I have list of Recipes and List of Alergens from user and I need to return List of Recipes in with products there is not any alergen from alergensOfUser list.
Each Recipe contains list of Products and each Product contains list of Alergens. How can I do it?
public class Recipe {
...
private List<Product> products;
}
public class Product {
...
private List<Alergen> alergens;
}
CodePudding user response:
Use Java streams. What we need to get is if recipe is made of products for which each of the product has no alergen in user's defined alergen.
List<Recipe> recipesList;
List<Alergen> userAllergens;
public List<Recipe> getRecipesForUser() {
return recipesList.stream()
.filter(recipe -> isNotMadeOfAlergen(recipe))
.collect(Collectors.toList());
}
public boolean isNotMadeOfAlergen(Recipe recipe) {
List<Product> productList = recipe.products;
return productList.stream().noneMatch(product -> containsAlergen(product));
}
public boolean containsAlergen(Product product) {
List<Alergen> alergenList = product.alergens;
return alergenList.stream()
.anyMatch(alergen -> userAllergens.contains(alergen));
}
CodePudding user response:
If you want to avoid 3 levels of nested streams, you can do this
List<Recipe> userEnteredRecipes; //populate it
List<Alergen> userEnteredAlergens; //populate it
List<Product> allProducts; //populate it
// first get products which have these alergens
List<Product> productsToAvoid =
allProducts.stream()
.filter(e -> e.getAlergens().stream().anyMatch(userEnteredAlergens::contains))
.collect(Collectors.toList());
// get the recipes which do not have these alergens
List<Recipe> filteredRecipes =
userEnteredRecipes.stream()
.filter(e -> (e.getProducts().stream().noneMatch(productsToAvoid::contains)))
.collect(Collectors.toList());