流操作類別

流操作分為兩大類,中間操作和終端操作,以及兩個子類,無狀態和有狀態。

中級操作:

中間操作總是很懶惰,比如簡單的 Stream.map。在實際使用流之前不會呼叫它。這可以很容易地驗證:

Arrays.asList(1, 2 ,3).stream().map(i -> {
    throw new RuntimeException("not gonna happen");
    return i;
});

中間操作是流的公共構建塊,連結在源之後,通常後跟觸發流鏈的終端操作。

終端操作

終端操作是觸發流消耗的原因。一些比較常見的是 Stream.forEachStream.collect。它們通常放在一系列中間操作之後,幾乎總是渴望

無國籍行動

無狀態意味著處理每個專案時沒有其他專案的上下文。無狀態操作允許對儲存器進行高效的流處理。像 Stream.mapStream.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);