首页 > 解决方案 > 包含不同对象的 2 个列表的公共部分

问题描述

我有两个列表,一个包含ProductDto,另一个包含ConsumedProductDto

@Builder
@Getter
@ToString
public class ProductDto {
    private final String id;
    private final String productName;
    private final Double calories;
    private final Double protein;
    private final Double fat;
    private final Double carbohydrates;
    private final Double weight;
}

@Getter
@Builder
@ToString
public class ConsumedProductDto {
    private final String username;
    private final LocalDate date;
    private final String productID;
    private final Double weight;
}

现在,我想获得这两个列表的共同部分,如果这些对象相等ProductDto.id == ConsumedProductDto.productID

我写了这个函数来做到这一点:

private List<ProductDto> matchingProducts(List<ProductDto> products, List<ConsumedProductDto> consumedProducts) {
        return products.stream().filter(product ->
                consumedProducts.stream()
                        .allMatch(consumedProduct ->
                              product.getId().equals(consumedProduct.getProductID())))
                .collect(Collectors.toList());
    }

它有效,直到我有两个(或更多)ConsumedProductDto具有相同productID的 . 然后,ProductDto当我想要两个(或更多)时,我只得到一个。

任何想法出了什么问题?另外,我知道我可以用 来@Override equals()检查那些共同的部分contains(),但是像这样混合 2 个不同的类是个好主意吗?

标签: javalistjava-stream

解决方案


正如我从对评论的回复中了解到的那样,您实际上是在根据过滤条件ProductDto在输出中为多个 s 查找多个条目以匹配此类产品。ConsumedProductDto

因此,您会感兴趣的是遍历consumedProductDtos 并找到 s 的任何匹配项,productDto并将map其收集到最终输出中。这可能类似于以下方法:

private List<ProductDto> matchingProducts(List<ProductDto> products, List<ConsumedProductDto> consumedProducts) {
    return consumedProducts.stream()
            .map(consumedProductDto -> products.stream()
                    .filter(productDto -> productDto.getId().equals(consumedProductDto.getProductID()))
                    .findAny().orElse(null))
            .filter(Objects::nonNull)
            .collect(Collectors.toList());
}

推荐阅读