How to group map values after Collectors.groupingBy() without using forEach

1.2k views Asked by At

I have a list of ProductDto objects and I want to group them the similar ones using java 8 streams Collectors.groupingBy(). After grouping the records I want to combine the similar records as single productDto. To achieve this I have used map.forEach and got the expected result, but I want to avoid the forEach loop and want to know any better solution in java 8.

Below is the my Main Class code snippet.

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

This is the ProductDto class code

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

Below is the screenshot image shows the input and output records. Output records is the results exactly I want it. Any alternate or better solution in java 8 which is efficient is most welcome. enter image description here

1

There are 1 answers

1
Chidambar Shiragalle On BEST ANSWER

After Rono comment I found the answer so posting the answer what I did in getGroupedResult method and added a new function mergetwoProduct. So this may help somebody. Below is the code for my getGroupedResult and mergetwoProduct methods after changes.

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