使用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
相关产品推荐
相关产品推荐

