Spliterator
的javadoc提到:
Spliterator可以单独遍历元素(tryAdvance())或按顺序遍历元素(forEachRemaining())。
然后我们转到javadoc of tryAdvance()
说:
如果存在剩余元素,则对其执行给定操作,返回true; else返回false。
也许我在某个地方误读了,但对我来说似乎只要剩下一个元素或更多,Consumer
作为一个参数应该只有每一个.accept()
返回true
之前的一个参数,如果我有两个参数可以立即使用,那么我就不能:
action.accept(arg1);
action.accept(arg2);
return true;
在this project中,我重写了广泛的第一个分裂器,现在它写着:
// deque is a Deque<Iterator<T>>
@Override
public boolean tryAdvance(final Consumer<? super T> action)
{
Iterator<T> iterator;
T element;
while (!deque.isEmpty()) {
iterator = deque.removeFirst();
while (iterator.hasNext()) {
element = iterator.next();
deque.add(fn.apply(element));
action.accept(element);
}
}
return false;
}
简而言之,我让action
接受所有参数,然后返回false ...而测试虽然很简单,但仍然成功(link)。
请注意,.trySplit()
始终返回null
;分词符具有特征DISTINCT
,ORDERED
和NONNULL
。
那么,是否有一个流使用,由于上面的方法一次性消耗所有元素,上面的代码将无法工作?
答案 0 :(得分:8)
您认为tryAdvance()
只应使用一个元素是正确的。但是,这并不意味着您会立即注意到违反合同的行为。当您使用.collect(Collectors.toList())
等操作进行测试时,甚至不太可能发现此类违规行为,因为大多数使用所有元素的操作都会在default
implementation is documented as:<的分裂器上调用forEachRemaining()
/ p>
默认实现重复调用tryAdvance(java.util.function.Consumer),直到返回false。
显然, 方法没有区别。
Stream框架将在执行延迟操作时调用tryAdvance()
。因此,当您使用.peek(System.out::println).findFirst()
时,如果tryAdvance()
实施推送多个值,您可能会发现存在差异。仍然,给出了当前的实现,结果是正确的第一个元素。显然,实现提供的消费者在遇到值后会忽略后续值。
这可能与“Why filter() after flatMap() is ‘not completely’ lazy in Java streams?”中讨论的其他实现细节相关联。如果流实现本身在某些情况下推送的值超过了必要的值,那么同一实现中的接收端必须准备好处理这种情况。
但必须强调的是,这是一个特定Stream API实现的行为。不同的实现或下一个Java版本可能依赖于tryAdvance
的正确实现。此外,除了Streams之外,Spliterator
可能还有用例。
好吧,我终于找到了一个与你的Spliterator
打破的操作示例:
for(Iterator<?> it=Spliterators.iterator(spliterator); it.hasNext();) {
System.out.println(it.next());
}