我在几个lambda项目邮件列表中做了调查,我想我发现了一些有趣的讨论。
到目前为止我还没有找到一个令人满意的解释。读完这些之后,我得出结论,这只是一个疏忽。但是你可以在这里看到,在API设计的这些年里,它被讨论了好几次。
Lambda lib规范专家
我在Lambda Libs Spec Experts邮件列表中找到了关于这个问题的讨论:
在Iterable/Iterator.stream()下Sam Pullara说:
I was working with Brian on seeing how limit/substream
functionality[1] might be implemented and he suggested conversion to
Iterator was the right way to go about it. I had thought about that
solution but didn't find any obvious way to take an iterator and turn
it into a stream. It turns out it is in there, you just need to first
convert the iterator to a spliterator and then convert the spliterator
to a stream. So this brings me to revisit the whether we should have
these hanging off one of Iterable/Iterator directly or both.
My suggestion is to at least have it on Iterator so you can move
cleanly between the two worlds and it would also be easily
discoverable rather than having to do:
Streams.stream(Spliterators.spliteratorUnknownSize(iterator,
Spliterator.ORDERED))
然后Brian Goetz回应道:
我想山姆的意思是有很多图书馆的课程
给你一个迭代器,但不让你自己写
spliterator。所以你能做的就是打电话
流(spliteratorUnknownSize (iterator))。山姆建议我们
定义Iterator.stream()来为你做这件事。
我想保留stream()和spliterator()方法
适用于库作者/高级用户。
后来
"鉴于编写Spliterator要比编写Iterator简单,
我宁愿只写一个Spliterator而不是一个Iterator (Iterator太90年代了:)”
不过,你没有抓住重点。外面有无数的课程
那里已经给了你一个迭代器。但他们中的许多人并不是
spliterator-ready。
Lambda邮件列表中的先前讨论
这可能不是你想要的答案,但在Project Lambda邮件列表中对此进行了简要的讨论。也许这有助于促进对这一主题进行更广泛的讨论。
用Brian Goetz在《Streams from Iterable》中的话说:
Stepping back...
There are lots of ways to create a Stream. The more information you
have about how to describe the elements, the more functionality and
performance the streams library can give you. In order of least to
most information, they are:
Iterator
Iterator + size
Spliterator
Spliterator that knows its size
Spliterator that knows its size, and further knows that all sub-splits
know their size.
(Some may be surprised to find that we can extract parallelism even
from a dumb iterator in cases where Q (work per element) is
nontrivial.)
If Iterable had a stream() method, it would just wrap an Iterator with
a Spliterator, with no size information. But, most things that are
Iterable do have size information. Which means we're serving up
deficient streams. That's not so good.
One downside of the API practice outlined by Stephen here, of
accepting Iterable instead of Collection, is that you are forcing
things through a "small pipe" and therefore discarding size
information when it might be useful. That's fine if all you're doing
to do is forEach it, but if you want to do more, its better if you
can preserve all the information you want.
The default provided by Iterable would be a crappy one indeed -- it
would discard size even though the vast majority of Iterables do know
that information.
矛盾吗?
虽然,看起来讨论是基于专家组对最初基于迭代器的Streams的初始设计所做的更改。
即便如此,有趣的是注意到在Collection这样的接口中,stream方法被定义为:
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
这可能与Iterable接口中使用的代码完全相同。
所以,这就是为什么我说这个答案可能不令人满意,但仍然值得讨论。
重构的证据
继续邮件列表中的分析,看起来splitIterator方法最初是在Collection接口中,在2013年的某个时候,他们将其移动到Iterable。
将splitIterator从Collection拉到Iterable。
结论/理论吗?
那么很有可能Iterable中缺少这个方法只是一个疏忽,因为当他们将splitIterator从Collection移动到Iterable时,看起来他们也应该移动stream方法。
如果还有其他原因,这些原因并不明显。还有人有其他的理论吗?