将两个foreach改为一个流(stream)

3

有没有人知道如何用 stream() 替换这个代码?

for (Customer customer : customers) {
    if (customer.getProducts() != null && customer.getProducts().getProduct() != null) {
        for (Product product : customer.getProducts().getProduct()) {
            if (product.getId().equals(productId)) {
                return Optional.of(product);
            }
        }
    }
}

我知道,第二个foreach可以替换为:

customer.getProducts().getProduct().stream().filter(a -> a.getId().equals(productId)).findAny();

但是我该如何使用一个流来替换两个foreach循环呢?


1
请查看flatMap()函数。 - JB Nizet
1
很可能是这个线程的重复。 - GuyKhmel
2个回答

4
使用flatMap获取所有Customer的所有ProductStream
Optional<Product> product =
    customers.stream()
             .filter(c -> c.getProducts() != null && c.getProducts().getProduct() != null)
             .flatMap(c -> c.getProducts().getProduct().stream())
             .filter(p -> p.getId().equals(productId))
             .findFirst();

2

像 @Eran 的答案已经是正确的了,我更喜欢以下方式。唯一的区别是每行只有一个操作(最终会有更多的行),这在我的眼中更加清晰:

Optional<Product> product = customers.stream()     // Stream<Customer>
         .map(Customer::getProducts)               // Stream<Products>
         .filter(Objects::nonNull)                 // filter null values out
         .map(Products::getProduct)                // Stream<Collection<Product>>
         .filter(Objects::nonNull)                 // filter null values out
         .flatMap(Collection::stream)              // Stream<Product>
         .filter(p -> p.getId().equals(productId)) // filter product with id out
         .findAny();                               // Optional<Product>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接