【问题标题】:How to group map values after Collectors.groupingBy() without using forEach如何在 Collectors.groupingBy() 之后对地图值进行分组而不使用 forEach
【发布时间】:2020-09-02 17:38:14
【问题描述】:

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

下面是我的主类代码sn-p。

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

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

下面是显示输入和输出记录的屏幕截图。输出记录正是我想要的结果。 Java 8 中任何有效的替代或更好的解决方案都是最受欢迎的。

【问题讨论】:

  • 可以但是不能跳过forEach里面的操作return new ArrayList&lt;&gt;(inputDtos.stream() .collect(Collectors.toMap(ProductDto::groupSimilarProductIdentifier, e -&gt; e, (a,b) -&gt; mergetwoProduct(a,b))).values());这里mergetwoProduct是一个合并两个产品并返回合并产品的函数
  • 或者...你也可以只使用map merge函数而不使用groupingBy,比如Map&lt;Object, ProductDto&gt; groupedMap = new HashMap&lt;&gt;(); inputDtos.forEach(e -&gt; groupedMap.merge(e.groupSimilarProductIdentifier(), e, (a,b) -&gt; mergetwoProduct(a,b)));
  • @Rono 是的,我已经将 forEach 中的逻辑提取到 mergetwoProduct 函数中。以上解决方案有效。非常感谢。

标签: java-8 java-stream collectors lightweight-stream-api


【解决方案1】:

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

【讨论】:

  • 另外,请记住您正在更改inputDtos 内部mergetwoProduct 的数据。您可以通过创建一个新对象并将这两个合并到该对象中并返回来避免这种情况
猜你喜欢
  • 2018-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-25
  • 2019-01-02
相关资源
最近更新 更多