Java 8:比较两个列表中的多个属性

时间:2015-10-07 12:40:27

标签: java loops java-8 java-stream

我刚开始在新项目中使用Java 8,现在我正在尝试转换一些旧代码。

我正在尝试转换为以下代码片段。这是一个前端测试,只是比较,如果productElements中的产品(代码)具有正确的数量:

for (Product product : products) {
    boolean productFound = false;
    for (ProductWebElement productElement : productElements) {
        if (productElement.getProductCode().equals(product.getCode())) {
            Assert.assertEquals(product.getQuantity(), productElement.getQuantity());
            productFound = true;
            break;
        }
    }
    // This is optional - can be ignored
    if (!productFound) {
        fail("Product: " + product.getCode() + " not found!");
    }
}

Product只是一个普通的数据类(String productCode, int quantity

ProductWebElementFluentWebElement的扩展对象 - 或者只是具有其他属性的对象。

我试图延伸 Java 8: More efficient way of comparing lists of different types?, 但我无法弄明白该怎么做。有谁知道如何用Java 8语法做到这一点?

2 个答案:

答案 0 :(得分:3)

您可以编写以下代码:

products.forEach(p -> {
    ProductWebElement productElement = productElements.stream().filter(
        pe -> pe.getProductCode().equals(p.getCode())
    ).findAny().orElseThrow(() -> new AssertionError("Product: " + p.getCode() + " not found!"));
    Assert.assertEquals(p.getQuantity(), productElement.getQuantity());
}); 

对于您的每个产品,我们都会尝试找到任何匹配的ProductElement(具有相同的产品代码)。

如果没有找到,我们抛出AssertionError。如果我们找到一个,我们可以断言数量是相同的。

答案 1 :(得分:3)

你应该摆脱一般的双重迭代。一种方法是将值存储在Map

Map<ProductCode,Quantity> map=productElements.stream().collect(
  Collectors.toMap(ProductWebElement::getProductCode, ProductWebElement::getQuantity));

products.forEach(product -> {
    Quantity q=map.get(product.getCode());
    if(q==null) fail("Product: " + product.getCode() + " not found!");
    Assert.assertEquals(product.getQuantity(), q);
});

请注意,由于您的属性的实际类型未显示在您的问题中,因此我在此处使用ProductCodeQuantity作为占位符。进一步请注意,我将实际的数量属性值存储在地图中,因为这是您感兴趣的唯一值,因此无需在第二个循环中再次查询ProductWebElement

这个逻辑也可以使用普通的Java 8之前的循环来实现......