回答
Stream
和Optional
之間存在根本差異。
A Stream
封裝了整個處理管道,在做任何事情之前收集所有操作。這允許實現根據實際請求的結果來選擇不同的處理策略。這也允許在鏈中插入修飾符如unordered()
或parallel()
,因爲到目前爲止還沒有做任何事情,所以我們可以改變後續實際處理的行爲。
一個極端的例子是Stream.of(1, 2, 3).map(function).count()
,這將不處理function
中的Java 9在所有,作爲3
不變結果可以在沒有被確定。
相反,Optional
只是一個值(如果不爲空)的包裝。每個操作都將立即執行,以返回封裝新值的新Optional
或空的Optional
。在Java 8中,返回Optional
(即map
,flatMap
或filter
)的所有方法只會在應用於空可選項時返回空可選項,因此在鏈接它們時,空可選項將成爲一種死衚衕。
但是Java 9會引入Optional<T> or(Supplier<? extends Optional<? extends T>>)
,當應用於空的可選項時,它可能會從供應商返回一個非空的可選項。
由於一個Optional
代表(可能是不存在的)價值,而不是處理管道,您可以查詢你想的一樣Optional
多次,查詢是否返回一個新Optional
或最終值。
這很容易驗證。下面的代碼
Optional<String> first=Optional.of("abc");
Optional<String> second=first.map(s -> {
System.out.println("Running map");
return s + "def";
});
System.out.println("starting queries");
System.out.println("first: "+(first.isPresent()? "has value": "is empty"));
System.out.println("second: "+(second.isPresent()? "has value": "is empty"));
second.map("second's value: "::concat).ifPresent(System.out::println);
將打印
Running map
starting queries
first: has value
second: has value
second's value: abcdef
證明映射函數立即評估,任何其他查詢之前,而我們,我們通過map
創造了第二後,仍然可以查詢first
可選查詢選項多次。
實際上,它是強烈推薦首先通過isPresent()
檢查,之後致電get()
。
沒有等效的流代碼,因爲這種方式重新使用Stream
實例是無效的。但我們可以表明,該終端操作已經開始前的中間操作不被執行:
Stream<String> stream=Stream.of("abc").map(s -> {
System.out.println("Running map");
return s + "def";
});
System.out.println("starting query");
Optional<String> result = stream.findAny();
System.out.println("result "+(result.isPresent()? "has value": "is empty"));
result.map("result value: "::concat).ifPresent(System.out::println);
將打印
starting query
Running map
result has value
result value: abcdef
表示映射函數沒有在終端操作findAny()
開始之前評價。由於我們無法多次查詢數據流,因此使用findAny()
甚至使用Optional
作爲返回值,這使我們可以用最終結果做到這一點。
同名的操作之間還存在其他語義差異,例如,如果映射函數評估爲null
,則Optional.map
將返回空的Optional
。對於一個流,傳遞給map
的函數返回null
或非null
值(這就是爲什麼我們可以在不知道它是否確定的情況下對其進行計數的原因)沒有區別。
String r = Optional.of("abc")
.map(s -> {
System.out.println("Running map");
return s + "def";
})
.filter(s -> {
System.out.println("First Filter");
return s.equals("abcdef");
})
.map(s -> {
System.out.println("mapping");
return s + "jkl";
})
.orElse("done");
System.out.println(r);
運行,這將產生:
運行圖,首先篩選,映射運行此abcdefjkl
在另一方面:
String r = Optional.of("mnt") //changed
.map(s -> {
System.out.println("Running map");
return s + "def";
})
.filter(s -> {
System.out.println("First Filter");
return s.equals("abcdef");
})
.map(s -> {
System.out.println("mapping");
return s + "jkl";
})
.orElse("done");
運行圖,第一個過濾器,完成
我一直以爲,既然是map
只執行基於以前filter
,這將被視爲lazy
。原來,這是不是真的:
Optional.of("s").map(String::toUpperCase)
Stream.of("test").map(String::toUpperCase)
從Optional
的map
將得到執行;而從Stream
不會。
編輯
去和贊成票這裏的其他答案。這是由於另一個編輯。
- 1. MVC中的動作類型過濾器?
- 2. 豬過濾器或操作
- 3. Servlet過濾器有選擇地工作
- 4. 我可以從操作過濾器返回操作結果嗎?
- 5. 錯誤與RDD過濾器,以星火2.1地圖操作和Python 3.5
- 6. 哈斯克爾地圖和過濾器
- 7. 過濾器,地圖,排序和concat
- 8. 計算器在C++中選擇不同的類型和操作
- 9. Sqlalchemy:使用兩個ARRAY類型列的過濾操作
- 10. Chrome和地圖之間的操作選擇器
- 11. SQLAlchemy的過濾器IN_操作
- 12. 基於UserAgent的過濾器操作
- 13. 地圖和過濾功能
- 14. 有兩個動作和類別的意圖過濾器
- 15. 任何不會丟棄的類似過濾器的lambda操作?
- 16. Django模板過濾器一直給出「不支持的操作數類型」
- 17. 按圖標類型過濾地圖標記
- 18. 導航操作意圖過濾
- 19. 選擇和過濾器不與d3.js餅圖工作
- 20. 撰寫一般過濾器類型類?
- 21. MySQL按位操作,布隆過濾器
- 22. 過濾器和過濾器
- 23. 如何在odata模型讀取操作中應用過濾器?
- 24. SaveFileDialog過濾器中的多種類型
- 25. MIME類型的QFileDialog過濾器
- 26. Sharepoint日期操作和過濾
- 27. Servicestack - 操作順序流暢的驗證和請求過濾器
- 28. Telerik報告中的可選過濾器
- 29. Xcode 6:Postfix「!」的操作數應該有可選的類型
- 30. 在自定義操作過濾器中注入存儲庫類
你可以通過在地圖或過濾器表達式中記錄某些東西,然後檢查什麼時候記錄東西來輕鬆驗證。 – luk2302
一行代碼會更有幫助:) –
不,最有幫助的將是你自己想出來,這樣你學到最多。 – luk2302