与C#不同IEnumerable
,执行管道可以根据需要执行多次,在Java中,流只能"迭代"一次.
对终端操作的任何调用都会关闭流,使其无法使用.这个"功能"消耗了很多力量.
我想这个的原因不是技术性的.这个奇怪限制背后的设计考虑是什么?
编辑:为了演示我在说什么,请考虑以下C#中的Quick-Sort实现:
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));
}
Run Code Online (Sandbox Code Playgroud)
现在可以肯定的是,我并不是说这是一个很好的快速排序!然而,它是lambda表达式与流操作相结合的表达能力的一个很好的例子.
它不能用Java完成!我甚至无法询问流是否为空而不使其无法使用.
Java 8引入了一个类似Scala的Stream的Stream类,这是一个功能强大的惰性结构,使用它可以非常简洁地执行这样的操作:
def from(n: Int): Stream[Int] = n #:: from(n+1)
def sieve(s: Stream[Int]): Stream[Int] = {
s.head #:: sieve(s.tail filter (_ % s.head != 0))
}
val primes = sieve(from(2))
primes takeWhile(_ < 1000) print // prints all primes less than 1000
Run Code Online (Sandbox Code Playgroud)
我想知道是否有可能在Java 8中这样做,所以我写了这样的东西:
IntStream from(int n) {
return IntStream.iterate(n, m -> m + 1);
}
IntStream sieve(IntStream s) {
int head = s.findFirst().getAsInt();
return IntStream.concat(IntStream.of(head), sieve(s.skip(1).filter(n -> n % head != 0)));
}
IntStream primes …
Run Code Online (Sandbox Code Playgroud)