Java 8中如何在flatMap后用groupingBy按属性分组对象
按产品分类构建
Map<String, List<Product>> 问题描述
需要构建一个Map<String, List<Product>>,其中Map的key为产品的分类(category),每个产品可归属多个分类。现有部分Stream代码,需补全flatMap之后的操作:
products.stream() .flatMap(product -> product.getCategories().stream()) . // 后续操作未知
期望输出结果:
{electonics=[p1,p3,p4], fashion=[p1,p2,p4], kitchen=[p1,p2,p3],abc1=[p2], xyz1=[p3],pqr1=[p4]}
产品实例及Product类定义:
Product p1 = new Product(123, Arrays.asList("electonics,fashion,kitchen".split(","))); Product p2 = new Product(123, Arrays.asList("abc1,fashion,kitchen".split(","))); Product p3 = new Product(123, Arrays.asList("electonics,xyz1,kitchen".split(","))); Product p4 = new Product(123, Arrays.asList("electonics,fashion,pqr1".split(","))); List<Product> products = Arrays.asList(p1, p2, p3, p4);
class Product { int price; List<String> categories; public Product(int price) { this.price = price; } public Product(int price, List<String> categories) { this.price = price; this.categories = categories; } public int getPrice() { return price; } public List<String> getCategories() { return categories; } }
解决方案
完整实现代码
原flatMap操作仅输出分类字符串,丢失了对应的产品对象,需先调整flatMap绑定分类与产品,再执行分组:
Map<String, List<Product>> categoryToProducts = products.stream() // 将每个产品转换为「分类-产品」键值对的流 .flatMap(product -> product.getCategories().stream() .map(category -> Map.entry(category, product))) // 按分类分组,收集对应产品列表 .collect(Collectors.groupingBy( Map.Entry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.toList()) ));
代码说明
- 调整flatMap:通过
map(category -> Map.entry(category, product)),把每个产品的每个分类转换为包含分类和产品自身的Map.Entry,确保流中同时保留分类与产品的关联关系。 - 分组收集:使用
Collectors.groupingBy按Map.Entry的key(分类)分组,再通过Collectors.mapping提取每个Entry中的产品对象,最终收集为List<Product>。
若使用Java 8及以下版本(无Map.entry),可自定义简单的配对类替代,核心逻辑保持一致。
内容的提问来源于stack exchange,提问作者Shiva
相关产品推荐
相关产品推荐

