javadoc Spliterator提到:
Spliterator可以单独遍历元素(tryAdvance())或顺序遍历元素(forEachRemaining()).
然后我们转到javadoc,tryAdvance()其中说:
如果存在剩余元素,则对其执行给定操作,返回true; else返回false.
也许我在某个地方误读,但对我来说似乎只要剩下一个或多个元素,Consumer作为一个参数应该只.accept()返回前的每个参数true,如果,比方说,我有两个参数立即可用,那么我不能:
action.accept(arg1);
action.accept(arg2);
return true;
Run Code Online (Sandbox Code Playgroud)
在这个项目中,我重写了广泛的第一个分裂器,现在它读取:
// 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;
}
Run Code Online (Sandbox Code Playgroud)
简而言之,我action接受所有参数,然后返回false ...而测试虽然很简单,但仍然成功(链接).
请注意,.trySplit()始终返回null; 分裂器具有特征DISTINCT,ORDERED并且NONNULL …
我注意到以下场景中出现了一些奇怪的行为:
迭代器 -> 流 -> map() -> 迭代器() -> 迭代
原始迭代器的 hasNext() 在返回 false 后又被调用一次。
这是正常的吗?
package com.test.iterators;
import java.util.Iterator;
import java.util.Spliterators;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class TestIterator {
private static int counter = 2;
public static void main(String[] args) {
class AdapterIterator implements Iterator<Integer> {
boolean active = true;
@Override
public boolean hasNext() {
System.out.println("hasNext() called");
if (!active) {
System.out.println("Ignoring duplicate call to hasNext!!!!");
return false;
}
boolean hasNext = counter >= 0;
System.out.println("actually has next:" + active); …Run Code Online (Sandbox Code Playgroud) 我在java.util.Spliterator (Java 8)中偶然发现了一个有趣的细节.
方法trySplit()应该返回Spliterator的一个实例null,如果它不能被拆分.java doc说如下:
* @return a {@code Spliterator} covering some portion of the
* elements, or {@code null} if this spliterator cannot be split.
Run Code Online (Sandbox Code Playgroud)
在我看来,它是一个完美的使用场所java.util.Optional.根据javadoc:
* A container object which may or may not contain a non-null value.
Run Code Online (Sandbox Code Playgroud)
有什么理由,为什么不使用Optional?
除了lambda-dev邮件列表中的这个问题外,谷歌搜索没有多大帮助,但没有回答.
我正在使用Java 8 Spliterator并创建一个将Fibonacci数字流式传输到给定的n.所以对于Fibonacci系列0, 1, 1, 2, 3, 5, 8, ...
n fib(n)
-----------
-1 0
1 0
2 1
3 1
4 2
Run Code Online (Sandbox Code Playgroud)
以下是我的实现,它在耗尽堆栈内存之前打印出一堆1.你能帮我找到这个bug吗?(我认为它没有推进,currentIndex但我不确定设置它的价值).
编辑1:如果您决定回答,请保持与问题相关.这个问题不是关于有效的斐波那契数生成; 这是关于学习分裂者的.
FibonacciSpliterator:
@RequiredArgsConstructor
public class FibonacciSpliterator implements Spliterator<FibonacciPair> {
private int currentIndex = 3;
private FibonacciPair pair = new FibonacciPair(0, 1);
private final int n;
@Override
public boolean tryAdvance(Consumer<? super FibonacciPair> action) {
// System.out.println("tryAdvance called.");
// System.out.printf("tryAdvance: currentIndex = %d, n = %d, pair = %s.\n", currentIndex, n, pair); …Run Code Online (Sandbox Code Playgroud) 该流接口有两个重载方法of().其中一个是变量方法,而另一个是一个参数.
单参数方法是一种性能优化,而不是将一个参数传递给变量方法?如果是这样,它如何提高性能?可以问这个empty()方法的相同问题,这似乎是围绕变量的语法糖of().
我看到这些方法的实现方式不同,显然差别在于如何Spliterator实例化; 但这为StreamAPI 提供了什么优势?
有谁知道为什么java.util.Spliterator当循环体为空时,实现使用 do-while 而不是 while 循环?例如,其实现forEachRemaining是:
default void forEachRemaining(Consumer<? super T> action) {
do { } while (tryAdvance(action));
}
Run Code Online (Sandbox Code Playgroud)
他们为什么要使用
do { } while (tryAdvance(action));
Run Code Online (Sandbox Code Playgroud)
代替
while(tryAdvance(action));
Run Code Online (Sandbox Code Playgroud)
?
有什么我不知道的优点吗?
关于深化认识Java流spliterators的第一个问题后,这里为什么执行:约溪流另一个微妙的问题.flatMap()在Java中是如此低效(非懒惰)?
通常,流应该尽可能地保持懒惰,但.flatMap()方法不是.
例如:
stream.flatMap(this::getStreamWith10HeavyComputationElems).firstFirst() 在返回第一个繁重的计算结果之前,将消耗10个元素(10次重计算).
stream.flatMap(this::getStreamWith10HeavyComputationElems).limit(11).count() 在返回11之前将消耗20个元素(2x10重计算).
该问题是为什么Java使用非懒实施?
@Test
void flatMap_native() throws Exception {
AtomicInteger count = new AtomicInteger();
Stream<Long> stream = LongStream.range(0, 5).boxed()
.flatMap(num -> LongStream.range(0, 10).boxed()
.peek(x -> count.incrementAndGet()))
.limit(11);
assertThat(stream).hasSize(11);
assertThat(count).hasValue(20); //!why? - should be 11!
}
Run Code Online (Sandbox Code Playgroud)
作为解决方法,我创建了自己的flatMap实现,但与本机调用相比,它缺乏流畅性:flatMap(stream, mapper)vs native stream.flatMap(mapper).
public static <T, R> Stream<R> flatMap(Stream<? extends T> stream, Function<? super T, ? extends Stream<? extends R>> mapper) {
// Outside the class …Run Code Online (Sandbox Code Playgroud) SpliteratorConsumer在其tryAdvance和forEachRemaining方法中采用任意函数.
如果消费者抛出异常,分裂者的状态应该是什么?如果消费者传递给forEachRemaining10个项目之后抛出异常(然后传播并捕获),tryAdvance那么分裂器中的下一个调用是否应返回第11个项目,或者该分裂器是否应该被视为死亡和无效?
javadocs在这一点上含糊不清; 他们只是说任何例外情况都会传播出去,而没有提到分裂者在那之后的状态
I am trying to understand the features of Spliterator and came across these 2 methods estimatedSize and getExactSizeIfKnown I could figure out what is estimatedSize but not sure exactly what doesgetExactSizeIfKnowndo. Can someone please give an example explaining the difference between the two.
EDIT: I tried the following example in which both of them are the same. In which cases would they be different?
public static void main(String[] args) {
List<Integer> l = new ArrayList<>();
l.add(1);
l.add(2);
l.add(3); …Run Code Online (Sandbox Code Playgroud) 我想从拆分器中获取下一个元素,而不仅仅是对下一个元素“执行操作”。例如,通过实现以下方法
<T> T getnext(Spliterator<T> s) {
}
Run Code Online (Sandbox Code Playgroud)
我发现的所有搜索结果都说tryAdvance()就像是迭代器hasNext()和next()的组合,除了那是一个大谎言,因为我无法获取下一个元素,只是“对下一个元素执行操作”。
spliterator ×10
java ×9
java-8 ×9
java-stream ×3
iterator ×2
concurrency ×1
consumer ×1
lambda ×1
overloading ×1