如何创建Map<String,List<Product>>个以下.这里,String(Map中的key)是Product中的category.

一个product可以属于multiple个类别,如下例所示.

我正在try 使用以下代码,但无法获得下一操作:

products.stream()
    .flatMap(product -> product.getCategories().stream())
    . // how should I progress from here?

结果应如下所示:

{Electron =[p1,p3,p4],时尚=[p1,p2,p4],厨房=[p1,p2,p3], Abc1=[p2],xyz1=[p3],pqr1=[p4]}

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;
    }
}

推荐答案

如果出于某种原因想要使用收集器groupingBy(),那么可以定义一个包装类(with Java 16+ a 100 would be more handy for that purpose),它将包含对categoryproduct的引用,以表示给定列表中存在的每个组合category/product.

public record ProductCategory(String category, Product product) {}

Java 16之前的替代版本:

public class ProductCategory {
    private String category;
    private Product product;
    
    // constructor and getters
}

然后在利用收集器mapping()toList()的组合作为groupingBy()downstream collector.

List<Product> products = // initializing the list of products
        
Map<String, List<Product>> productsByCategory = products.stream()
    .flatMap(product -> product.getCategories().stream()
        .map(category -> new ProductCategory(category, product)))
    .collect(Collectors.groupingBy(
        ProductCategory::category,                   // ProductCategory::getCategory if you used a class instead of record
        Collectors.mapping(ProductCategory::product, // ProductCategory::getProduct if you used a class instead of record
            Collectors.toList())
    ));

A link to Online-Demo


但是,more performant选项不是创建中间对象和生成嵌套流,而是描述collect()three-args version内的累积策略(或定义custom collector).

这就是它可能的实施方式:

Map<String, List<Product>> productsByCategory = products.stream()
    .collect(
        HashMap::new,
        (Map<String, List<Product>> map, Product next) -> next.getCategories()
            .forEach(category -> map.computeIfAbsent(category, k -> new ArrayList<>())
                .add(next)),
        (left, right) -> right.forEach((k, v) -> 
            left.merge(k, v,(oldProd, newProd) -> { oldProd.addAll(newProd); return oldProd; }))
    );

A link to Online-Demo

Java相关问答推荐

将具有多个未知字段的SON映射到Java POJO

scanner 如何在执行hasNextLine一次后重新读取整个文件?

Java inline Double条件和值解装箱崩溃

蒙蒂霍尔比赛结果不正确

如何在ApachePOI中将图像添加到工作表的页眉?

使用Spring和ActiveMQ的侦听器方法引发属性名称不能重复为空警告

对于亚洲/香港,使用ResolverStyle.STRICT的LocalDate.parse返回意外结果

将java.util.Date转换为OffsetDateTime

为什么Spring Boot项目无法为基于MySQL的CRUD应用程序找到从JPARepository接口扩展的ProductRepository?

@Rollback @ Transmission在验收测试中不工作

Spring-Boot Kafka应用程序到GraalVM本机映像-找不到org.apache.kafka.streams.processor.internals.DefaultKafkaClientSupplier

Java在操作多个属性和锁定锁对象时使用同步和易失性

我的代码是线程安全的吗?[Java、CAS、转账]

为什么JavaFX MediaPlayer音频播放在Windows和Mac上运行良好,但在Linux(POPOS/Ubuntu)上却有问题?

在单例类上获取Java锁,了解原因

为什么Instant没有从UTC转换为PostgreSQL的时区?

由于可为null,无法在kotlin中实现java接口

如何使用我的RLE程序解决此问题

为什么我得到默认方法的值而不是被覆盖的方法的值?

一条Java记录可以保存多少个字段?