3 回答

TA貢獻1780條經驗 獲得超4個贊
您的終端操作 ,toArray()可能支持您的論點,因為它需要流的所有元素。
一些終端操作沒有。而對于這些,如果不是懶惰地執行流,那將是一種浪費。兩個例子:
//example 1: print first element of 1000 after transformations
IntStream.range(0, 1000)
.peek(System.out::println)
.mapToObj(String::valueOf)
.peek(System.out::println)
.findFirst()
.ifPresent(System.out::println);
//example 2: check if any value has an even key
boolean valid = records.
.map(this::heavyConversion)
.filter(this::checkWithWebService)
.mapToInt(Record::getKey)
.anyMatch(i -> i % 2 == 0)
第一個流將打?。?/p>
0
0
0
也就是說,中間操作將只在一個元素上運行。這是一個重要的優化。如果不是懶惰,那么所有peek()調用都必須在所有元素上運行(絕對沒有必要,因為您只對一個元素感興趣)。中間操作可能很昂貴(例如在第二個示例中)
短路端子操作(toArray不是)使這種優化成為可能。

TA貢獻1757條經驗 獲得超8個贊
惰性對于 API 的用戶非常有用,尤其是當Stream管道評估的最終結果可能非常大時!
簡單的例子是Files.linesJava API 本身中的方法。如果您不想將整個文件讀入內存并且只需要第一N行,那么只需編寫:
Stream<String> stream = Files.lines(path); // lazy operation
List<String> result = stream.limit(N).collect(Collectors.toList()); // read and collect

TA貢獻2003條經驗 獲得超2個贊
我有一個來自我們代碼庫的真實示例,因為我將對其進行簡化,但不完全確定您可能喜歡它還是完全掌握它...
我們有一個需要 的服務List<CustomService>
,我想稱之為?,F在為了調用它,我要去一個數據庫(比現實簡單得多)并獲得一個List<DBObject>
; 為了從中獲得a List<CustomService>
,需要進行一些重大的轉換。
這是我的選擇,就地轉換并傳遞列表。很簡單,但可能不是那么理想。第二種選擇,重構服務,接受 aList<DBObject>
和 a Function<DBObject, CustomService>
。這聽起來微不足道,但它使懶惰(除其他外)成為可能。該服務有時可能只需要該 List 中的幾個元素,或者有時需要max
某個屬性等 - 因此我不需要對所有元素進行大量轉換,這就是Stream API
基于拉的懶惰是贏家的地方。
在 Streams 出現之前,我們曾經使用guava
. 它也Lists.transform( list, function)
很懶惰。
這不是流的基本特征,即使沒有番石榴也可以完成,但這樣要簡單得多。這里提供的例子findFirst
很好,而且最容易理解;這就是懶惰的全部意義所在,元素僅在需要時才被拉取,它們不會從一個中間操作以塊的形式傳遞到另一個操作,而是一次從一個階段傳遞到另一個階段。
添加回答
舉報