2017-12-18 369 views
3

有人可能有任何想法如何将其替换为stream()更改两个foreach到一个流

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

但我怎么能更换一个流都foreachs?

+1

查找到flatMap() –

+1

大概[该线程的重复](https://stackoverflow.com/questions/34406744/refactoring-a-nested-foreach-into-java-8-stream) – GuyKhmel

回答

4

使用flatMap得到所有Customer s的所有Product中的Stream

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>