流操作類別
流操作分為兩大類,中間操作和終端操作,以及兩個子類,無狀態和有狀態。
中級操作:
中間操作總是很懶惰,比如簡單的 Stream.map
。在實際使用流之前不會呼叫它。這可以很容易地驗證:
Arrays.asList(1, 2 ,3).stream().map(i -> {
throw new RuntimeException("not gonna happen");
return i;
});
中間操作是流的公共構建塊,連結在源之後,通常後跟觸發流鏈的終端操作。
終端操作
終端操作是觸發流消耗的原因。一些比較常見的是 Stream.forEach
或 Stream.collect
。它們通常放在一系列中間操作之後,幾乎總是渴望。
無國籍行動
無狀態意味著處理每個專案時沒有其他專案的上下文。無狀態操作允許對儲存器進行高效的流處理。像 Stream.map
和 Stream.filter
這樣的操作不需要關於流的其他專案的資訊被認為是無狀態的。
有狀態的操作
有狀態意味著每個專案的操作取決於流的(某些)其他專案。這需要保留一個狀態。有狀態操作可能會破壞長流或無限流。像 Stream.sorted
這樣的操作需要在發出任何專案之前處理整個流,這將在足夠長的專案流中中斷。這可以通過長流來證明( 執行風險自負 ):
// works - stateless stream
long BIG_ENOUGH_NUMBER = 999999999;
IntStream.iterate(0, i -> i + 1).limit(BIG_ENOUGH_NUMBER).forEach(System.out::println);
由於 Stream.sorted
的狀態,這將導致記憶體不足:
// Out of memory - stateful stream
IntStream.iterate(0, i -> i + 1).limit(BIG_ENOUGH_NUMBER).sorted().forEach(System.out::println);