Java 8 如何在不使用forEach的情况下在Collector.groupingBy()之后对映射值进行分组

Java 8 如何在不使用forEach的情况下在Collector.groupingBy()之后对映射值进行分组,java-8,java-stream,collectors,lightweight-stream-api,Java 8,Java Stream,Collectors,Lightweight Stream Api,我有一个ProductDto对象列表,我想使用Java8 streams Collector.groupingBy()将它们与类似的对象分组。在对记录进行分组后,我希望将类似的记录合并为单个productDto。为了实现这一点,我使用了map.forEach并获得了预期的结果,但我想避免forEach循环,并想了解java 8中的任何更好的解决方案 下面是我的主要类代码片段 public class GroupTest { public static void main(String[] ar

我有一个ProductDto对象列表,我想使用Java8 streams Collector.groupingBy()将它们与类似的对象分组。在对记录进行分组后,我希望将类似的记录合并为单个productDto。为了实现这一点,我使用了map.forEach并获得了预期的结果,但我想避免forEach循环,并想了解java 8中的任何更好的解决方案

下面是我的主要类代码片段

public class GroupTest {

public static void main(String[] args) {
    GroupTest t=new GroupTest();
    List<ProductDto> inputDtos=t.createInputData();
    List<ProductDto> resultDtos=t.getGroupedResult(inputDtos);
    //writing to Excel
}

private List<ProductDto> getGroupedResult(List<ProductDto> inputDtos) {
    
    Map<Object, List<ProductDto>> groupedMap = inputDtos.stream()
            .collect(Collectors.groupingBy(ProductDto::groupSimilarProductIdentifier));
    
    List<ProductDto> resultProductDtos=new ArrayList<>();

    groupedMap.forEach((key, dtos) -> {
        if (dtos.size() > 1) {
            ProductDto productDto = dtos.get(0);
            dtos.forEach(dto -> {
                if (dto.getLap1() != null) {
                    productDto.setLap1(dto.getLap1());
                } else if (dto.getLap2() != null) {
                    productDto.setLap2(dto.getLap2());
                } else if (dto.getLap3() != null) {
                    productDto.setLap3(dto.getLap3());
                }
            });
            resultProductDtos.add(productDto);
        } else {
            resultProductDtos.addAll(dtos);
        }
    });
    
    return resultProductDtos;
}

private List<ProductDto> createInputData(){
    List<ProductDto> dtos=new ArrayList<>();
    dtos.add(new ProductDto(1L,"DELL",8,"DELL_s001",null,null));
    dtos.add(new ProductDto(1L,"DELL",8,null,"DELL_s002",null));
    dtos.add(new ProductDto(1L,"DELL",8,null,null,"DELL_s003"));
    dtos.add(new ProductDto(1L,"HP",8,"HP_s001",null,null));
    dtos.add(new ProductDto(2L,"APPLE",16,"MAC_s001",null,null));
    return dtos;
}
}
公共类组测试{
公共静态void main(字符串[]args){
GroupTest t=新的GroupTest();
List inputDtos=t.createInputData();
列表结果TOS=t.getGroupedResult(inputDtos);
//编写Excel
}
私有列表getGroupedResult(列表输入操作){
Map groupedMap=inputDtos.stream()
.collect(Collectors.groupingBy(ProductDto::groupSimilarProductIdentifier));
List resultProductDtos=new ArrayList();
groupedMap.forEach((键,DTO)->{
如果(dtos.size()>1){
ProductDto ProductDto=dtos.get(0);
dtos.forEach(dto->{
if(dto.getLap1()!=null){
productDto.setLap1(dto.getLap1());
}else if(dto.getLap2()!=null){
productDto.setLap2(dto.getLap2());
}else if(dto.getLap3()!=null){
productDto.setLap3(dto.getLap3());
}
});
结果productdtos.add(productDto);
}否则{
结果产品dtos.addAll(dtos);
}
});
返回resultproducttos;
}
私有列表createInputData(){
List dtos=new ArrayList();
添加(新产品DTO(1L,“DELL”,8,“DELL_s001”,null,null));
添加(新产品DTO(1L,“DELL”,8,空,“DELL_s002”,空));
添加(新产品DTO(1L,“戴尔”,8,空,空,“戴尔s003”);
添加(新产品DTO(1L,“HP”,8,“HP_s001”,null,null));
添加(新产品DTO(2L,“苹果”,16,“MAC_s001”,空,空);
返回DTO;
}
}
这是ProductDto类代码

public class ProductDto {
private Long userId;
private String manufacter;
private int ram;
private String lap1;
private String lap2;
private String lap3;

public ProductDto(Long userId, String manufacter, int ram, String lap1, String lap2, String lap3) {
    super();
    this.userId = userId;
    this.manufacter = manufacter;
    this.ram = ram;
    this.lap1 = lap1;
    this.lap2 = lap2;
    this.lap3 = lap3;
}
//getters and Setters

public List<Object> groupSimilarProductIdentifier() {
    return Arrays.asList(userId, manufacter, ram);
}
}
公共类产品到{
私有长用户ID;
私人字符串制造商;
私有内存;
私有字符串lap1;
私有字符串lap2;
私有字符串lap3;
公共产品DTO(长用户ID、字符串制造商、int ram、字符串lap1、字符串lap2、字符串lap3){
超级();
this.userId=userId;
这个。制造商=制造商;
this.ram=ram;
这1.lap1=lap1;
这是lap2=lap2;
这是lap3=lap3;
}
//接球手和接球手
公共列表groupSimilarProductIdentifier(){
返回Arrays.asList(userId、manufacturer、ram);
}
}
下面是显示输入和输出记录的屏幕截图。输出记录的结果正是我想要的。最受欢迎的是java 8中任何高效的替代或更好的解决方案。

Rono评论之后,我找到了答案,因此发布了我在getGroupedResult方法中所做的回答,并添加了一个新函数mergetwoProduct。所以这可能会帮助一些人。 下面是更改后getGroupedResult和mergetwoProduct方法的代码

private List<ProductDto> getGroupedResult(List<ProductDto> inputDtos) {
    List<ProductDto> productdtos= new ArrayList<>(inputDtos.stream().collect(
            Collectors.toMap(ProductDto::groupSimilarProductIdentifier, e -> e, (a, b) -> mergetwoProduct(a, b)))
            .values());
    return productdtos;
}

private ProductDto mergetwoProduct(ProductDto p1,ProductDto p2) {
    if (p2.getLap1() != null) {
        p1.setLap1(p2.getLap1());
    } else if (p2.getLap2() != null) {
        p1.setLap2(p2.getLap2());
    } else if (p2.getLap3() != null) {
        p1.setLap3(p2.getLap3());
    }
    return p1;
}
private List getGroupedResult(List inputDtos){
List productdtos=new ArrayList(inputDtos.stream().collect(
toMap(ProductDto::groupSimilarProductIdentifier,e->e,(a,b)->mergetwoProduct(a,b)))
.values());
退货;
}
私有产品到mergetwoProduct(产品到p1,产品到p2){
if(p2.getLap1()!=null){
p1.setLap1(p2.getLap1());
}else if(p2.getLap2()!=null){
p1.setLap2(p2.getLap2());
}else if(p2.getLap3()!=null){
p1.setLap3(p2.getLap3());
}
返回p1;
}

您可以这样做,但不能跳过forEach中的操作
返回新的ArrayList(inputDtos.stream().collect(Collectors.toMap(ProductDto::groupSimilarProductIdentifier,e->e,(a,b)->mergetwoProduct(a,b)).values()
此处
mergetwoProduct
是一个函数,用于合并两个产品并返回合并的产品或。。。您也可以仅使用map
merge
函数,而不使用
groupingBy
类似的
map groupedMap=new HashMap();inputDtos.forEach(e->groupedMap.merge(e.groupSimilarProductIdentifier(),e,(a,b)->mergetowproduct(a,b))
@Rono没错,我已经取出forEach内部的逻辑来合并TwoProduct函数。上述解决方案有效。非常感谢。另外,请记住,您正在更改
inputDtos
内部
mergetwoProduct
的数据。您可以通过创建一个新对象并将这两个对象合并到该对象中并返回