我惊讶地看到,lines()方法使用Iterator<T>接口的实现而不是Spliterator<T>来创建Stream<T>的实例。由于许多原因,即使没有并行性,使用Spliterator<T>也有几个优点。例如,Brian Goetz states in its answer to question Iterator versus Stream of Java 8
Spliterator的每个元素访问成本从根本上低于Iterator,甚至按顺序计算。
那么,为什么BufferedReader::lines()通过Iterator<T>而不是Spliterator<T>创建了一个Stream<T>?
发布于 2016-05-27 13:53:15
使用Iterator实现它没有技术上的原因。布赖恩·戈茨的声明仍然有效。为什么我怀疑在这种特定情况下您是否会注意到性能差异,基于Spliterator的实现会简单得多,因为它所需要的只是一个调用readLine()的tryAdvance方法实现,而迭代器实现必须保持状态才能记住hasNext()是否已经被调用以及结果如何。
所以实际的原因是同样的原因,为什么这里的很多开发人员都这么做。迭代器是熟悉的,因此开发人员很快就会实现它,因为他们知道他们可以包装它(在我之前的回答中,我也这么做了)。在JRE开发中,可能有一个历史原因,例如它是在引入Spliterator之前实现的,之后才进行重构。
请注意,还有一些更糟糕的问题,比如String.chars(),它可以作为一个快速、轻量级、基于数组的分配器来实现,并具有完善的并行支持。相反,您将得到一个基于PrimitiveIterator.OfInt的Java 8实现,它更复杂,性能浪费,并且本质上具有糟糕的并行支持(底层实现必须缓冲数据)。
值得庆幸的是,String.chars()将在Java9中得到修复,这并不意味着每个参与的开发人员都得到了消息。我刚才看了一下Matcher.results(),它是在Java 9中引入的,它还使用了Iterator绕道(与Scanner.findAll相反,给出了一个正面的反例)。当然,在发布之前,这一切都可能发生变化。
但是,流生成方法中不必要的Iterator弯路不太可能很快消失。在某些情况下,在方法以…的方式实现之后,重写这些方法甚至不值得浪费时间
https://stackoverflow.com/questions/37483451
复制相似问题