Issue
I have a List
of Product
s and every product contains a list of Ingredient
s.
public class Product {
private String id;
private List<Ingredient> ingredients;
// other code
}
public class Ingredient {
private String name;
// other code
}
I want to collect products into Map
grouping them by each ingredient.
How can I do it by using Stream API's collect()
and Collectors.groupingBy()
?
Product p1 = new Product("1", Arrays.asList(new Ingredient("i1"), new Ingredient("i2"), new Ingredient("i3")));
Product p2 = new Product("2", Arrays.asList(new Ingredient("i1"), new Ingredient("i3"), new Ingredient("i5")));
Product p3 = new Product("3", Arrays.asList(new Ingredient("i2"), new Ingredient("i4"), new Ingredient("i5")));
List<Product> products = List.of(p1, p2, p3);
Map<Ingredient, List<Product>> result = products.stream()
.collect(Collectors.groupingBy( not_sure_what_needs_to_go_here ));
The expected result should look like:
[i1 : {p1, p2} ,
i2 : {p1, p3} ,
i3 : {p1, p2},
i4 : {p3} ,
i5 : {p2, p2}]
Solution
You can create a Tuple
@Value
static class Tuple<L, R> {
L left;
R right;
}
or a Java record
public record IngProd (Ingredient ingredient, Product product) {}
and then stream over your products flatmapping to a tuple and collect using grouping by
Map<Ingredient, List<Product>> result =
products.stream()
.flatMap(prod -> prod.getIngredients().stream().map(ing -> new Tuple<>(ing, prod)))
.collect(groupingBy(Tuple::getLeft, mapping(Tuple::getRight, toList())));
when using a record change
Tuple::getLeft & Tuple::getRight
to
IngProd::getIngredient & IngProd::getProduct
Answered By - Eritrean
Answer Checked By - Cary Denson (JavaFixing Admin)