You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Java Stream API多字段分组将ProductWithComments转为Product集合

实现方案

前置准备

首先需要给三个POJO补充必要的getter、setter、构造方法,同时建议给Product类的comments属性做初始化避免空指针,示例如下:

import java.util.List;

class Product{
    private String productName;
    private String productCode;
    private String price;
    private String productId;
    private String country;
    private List<Comments> comments;

    // 无参构造
    public Product() {}
    // 全参构造
    public Product(String productName, String productCode, String price, String productId, String country, List<Comments> comments) {
        this.productName = productName;
        this.productCode = productCode;
        this.price = price;
        this.productId = productId;
        this.country = country;
        this.comments = comments;
    }
    // 所有字段的getter和setter
    public String getProductName() {return productName;}
    public void setProductName(String productName) {this.productName = productName;}
    public String getProductCode() {return productCode;}
    public void setProductCode(String productCode) {this.productCode = productCode;}
    public String getPrice() {return price;}
    public void setPrice(String price) {this.price = price;}
    public String getProductId() {return productId;}
    public void setProductId(String productId) {this.productId = productId;}
    public String getCountry() {return country;}
    public void setCountry(String country) {this.country = country;}
    public List<Comments> getComments() {return comments;}
    public void setComments(List<Comments> comments) {this.comments = comments;}
}

class Comments {
    private String productCode;
    private String languageCode;
    private String comment;

    public Comments() {}
    public Comments(String productCode, String languageCode, String comment) {
        this.productCode = productCode;
        this.languageCode = languageCode;
        this.comment = comment;
    }
    // 所有字段的getter和setter
    public String getProductCode() {return productCode;}
    public void setProductCode(String productCode) {this.productCode = productCode;}
    public String getLanguageCode() {return languageCode;}
    public void setLanguageCode(String languageCode) {this.languageCode = languageCode;}
    public String getComment() {return comment;}
    public void setComment(String comment) {this.comment = comment;}
}

class ProductWithComments{
    private String productName;
    private String productCode;
    private String price;
    private String productId;
    private String country;
    private String comment;
    private String languageCode;

    // 所有字段的getter
    public String getProductName() {return productName;}
    public String getProductCode() {return productCode;}
    public String getPrice() {return price;}
    public String getProductId() {return productId;}
    public String getCountry() {return country;}
    public String getComment() {return comment;}
    public String getLanguageCode() {return languageCode;}
}

如果项目引入了Lombok,直接给类加@Data、@NoArgsConstructor、@AllArgsConstructor注解即可省略以上样板代码。

核心实现

多字段分组的核心是构造基于分组字段的唯一键,这里提供两种兼容不同Java版本的实现方案:

方案1:Java 8+通用实现(无需额外定义类)

直接用Arrays.asList()封装五个分组字段作为键,List的equals和hashCode方法天然基于元素内容判断,适合作为分组键:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class ConvertDemo {
    public List<Product> convert(List<ProductWithComments> productWithCommentsList) {
        return productWithCommentsList.stream()
                // 按五个字段分组,下游直接将同组数据转换为Comments列表
                .collect(Collectors.groupingBy(
                        pwc -> Arrays.asList(
                                pwc.getProductName(),
                                pwc.getProductCode(),
                                pwc.getPrice(),
                                pwc.getProductId(),
                                pwc.getCountry()
                        ),
                        Collectors.mapping(pwc -> new Comments(
                                pwc.getProductCode(),
                                pwc.getLanguageCode(),
                                pwc.getComment()
                        ), Collectors.toList())
                ))
                // 遍历分组结果转换为Product对象
                .entrySet()
                .stream()
                .map(entry -> {
                    Product product = new Product();
                    List<?> key = entry.getKey();
                    product.setProductName((String) key.get(0));
                    product.setProductCode((String) key.get(1));
                    product.setPrice((String) key.get(2));
                    product.setProductId((String) key.get(3));
                    product.setCountry((String) key.get(4));
                    product.setComments(entry.getValue());
                    return product;
                })
                .collect(Collectors.toList());
    }
}

方案2:Java 16+ 更优雅实现(用record作为分组键)

Java 16以上版本可以用record定义不可变的分组键,避免类型强转,可读性更高:

import java.util.List;
import java.util.stream.Collectors;

public class ConvertDemo {
    // 定义不可变分组键
    record ProductKey(String productName, String productCode, String price, String productId, String country) {}

    public List<Product> convert(List<ProductWithComments> productWithCommentsList) {
        return productWithCommentsList.stream()
                .collect(Collectors.groupingBy(
                        pwc -> new ProductKey(
                                pwc.getProductName(),
                                pwc.getProductCode(),
                                pwc.getPrice(),
                                pwc.getProductId(),
                                pwc.getCountry()
                        ),
                        Collectors.mapping(pwc -> new Comments(
                                pwc.getProductCode(),
                                pwc.getLanguageCode(),
                                pwc.getComment()
                        ), Collectors.toList())
                ))
                .entrySet()
                .stream()
                .map(entry -> new Product(
                        entry.getKey().productName(),
                        entry.getKey().productCode(),
                        entry.getKey().price(),
                        entry.getKey().productId(),
                        entry.getKey().country(),
                        entry.getValue()
                ))
                .collect(Collectors.toList());
    }
}

内容的提问来源于stack exchange,提问作者KItis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 14:45:03