与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完成!我甚至无法询问流是否为空而不使其无法使用.
假设您要构建ImmutableSet/ List/ Map对象的副本,但过滤掉一些原始条目.实现这一目标的一种方法如下:
ImmutableList.copyOf(Iterables.filter(myObject, myObject.EQUALS));
Run Code Online (Sandbox Code Playgroud)
where myObject.EQUALS是Iterables.filter()操作的谓词.我认为这是一个非常优雅且易于阅读的实现.但是,一个构建两个列表对象(第一个通过Iterables.filter(...)调用,第二个通过ImmutableList.copyOf(...)),这是非常低效的.
有人知道更有效的方法吗?
我想最好的事情是将过滤器谓词添加到ImmutableSet/ List/ Map构建器,以便该对象必须只构造一次.但不幸的是,没有这样的参数.