2017-04-19 67 views
3

這個問題可以基於考慮java 8 nested streams的Java 8嵌套流:在最後一個流返回值

假設我有一個BatchBasket s的Item S:

public class Batch { 
    private List<Basket> baskets; 
} 

public class Basket { 
    private List<Item> items; 
} 

public class Item { 
    private String property; 
    private int value; 
} 

我想用Java 8流重寫此方法。

public class SomeService { 
    public int findValueInBatch(Batch batch) { 
     for (Basket basket : batch.getBaskets()) { 
      for (Item item : basket.getItems()) { 
       if (item.getProperty().equals("someValue") { 
        return item.getValue(); 
       } 
      } 
     } 
     return 0; 
    } 
} 

我應該怎麼做?

第一步,我想哪裏去:

public int findValueInBatch(Batch batch) { 
    for (Basket basket : batch.getBaskets()) { 
     basket.getItems().stream() 
      .filter(item -> item.getProperty.equals("someValue") 
      .findFirst() 
      .get(); 
      // there I should 'break' 
    } 
} 

非常感謝。

+0

您的原始方法不會編譯。 – shmosel

+0

@shmosel true,我缺少括號item.getProperty()和一個返回值,如果沒有找到元素。目標是顯示原則。固定。 – user3165278

回答

2
baskets.stream() 
      .flatMap(basket -> basket.getItems().stream()) 
      .filter(item -> item.equals("someValue")) 
      .findAny() 
      .orElseThrow(NoSuchElementException::new); 

使用findAny代替findFirstfindFirst不平行流工作的優勢。因此,如果要並行執行上述操作,您只需將stream()方法替換爲parallel()

+0

所有的答案都合適,多虧了。我選擇這個爲findAny小費。我們可以返回一個Optional,然後測試結果isPresent(),而不是拋出異常。 – user3165278

3

爲了消除這兩個循環,您可以使用flatMap生產的所有Item一切都在Basket S的的Stream<Item>

return batch.getBaskets() 
      .stream() 
      .flatMap(b -> b.getItems().stream()) 
      .filter(item -> item.getProperty.equals("someValue")) 
      .findFirst() 
      .orElse(some default value); // using .get() would throw an exception 
             // if no match is found 
3
  1. 使用flatMap得到嵌套列表的順風車,提取每個List<Item>,轉他們分成Stream<Item>,就像所有的子流合併在一起。
  2. 使用filter忽略不匹配的元素。
  3. 使用findFirst只得到第一次出現和停止處理
  4. 使用orElseThrow拋出一個異常,如果沒有someValue中的occurence被發現。

在這裏你去

public class SomeService { 
    public int findValueInBatch(Batch batch) { 
     return batch.getBaskets().stream() 
      .flatMap(basket -> basket.getItems().stream()) 
      .filter(item -> item.getProperty.equals("someValue")) 
      .findFirst() 
      .orElseThrow(() -> new IllegalArgumentException("value not found")); 
    } 
} 
+0

感謝您對flatMap的清晰解釋,真的有所幫助。一個細節:IllegalArgumentException在這裏並不適合(不是問題的核心)。 – user3165278

+0

沒問題,我用它作爲佔位符,但你可以使用適合你需要的那個。甚至使用'orElse(一個默認的int值)',但我寧願使用orElseThrow如果我是你 –