Why are Java Streams once-off?

Unlike C#’s IEnumerable, where an execution pipeline can be executed as many times as we want, in Java a stream can be ‘iterated’ only once.

Any call to a terminal operation closes the stream, rendering it unusable.
This ‘feature’ takes away a lot of power.

I imagine the reason for this is not technical. What were the design considerations behind this strange restriction?

Edit: in order to demonstrate what I am talking about, consider the following implementation of Quick-Sort in C#:

IEnumerable<int> QuickSort(IEnumerable<int> ints)
{
  if (!ints.Any()) {
    return Enumerable.Empty<int>();
  }

  int pivot = ints.First();

  IEnumerable<int> lt = ints.Where(i => i < pivot);
  IEnumerable<int> gt = ints.Where(i => i > pivot);

  return QuickSort(lt).Concat(new int[] { pivot }).Concat(QuickSort(gt));
}

Now to be sure, I am not advocating that this is a good implementation of quick sort! It is however great example of the expressive power of lambda expression combined with stream operation.

And it can’t be done in Java!
I can’t even ask a stream whether it is empty without rendering it unusable.

6 Answers
6

Leave a Comment