用和对象的方法初始化Stream的最佳方法是什么?
Foo foo1 = new Foo();
Foo foo2 = foo1.getNext();
Foo foo3 = foo2.getNext();
我想要通过getNext()方法的foo,foo1,foo2等流。
我尝试过
Stream.iterate
Stream.generate
但是这些方法会返回无限流。
答案 0 :(得分:0)
首先想到的是使用limit
截断流:
Stream.iterate(foo1, Foo::getNext)
.limit(size)....
但是很明显,如果大小未知,这是没有用的。
如果大小未知,那么肯定会有某种条件说“停下来,别无所求”。
Stream.iterate(foo1, Foo::getNext)
.takeWhile(f -> someCondition)
.... // further intermediate or a terminal operation
或:
Stream.iterate(foo1, f -> someCondition, Foo::getNext)
.... // further intermediate or a terminal operation
如果您不能使用JDK-9,那么您唯一的选择是创建自己的帮助器方法来执行您要遵循的逻辑。
答案 1 :(得分:0)
问题中未指定它,但是我相信您想在getNext()
返回null
时停止迭代(这似乎是最有意义的)。
如果是这样,至少有三种方法:
如果在JDK 9+上,请执行Aominè建议的操作:
Stream.iterate(foo1, Objects::nonNull, Foo::getNext)
如果在JDK 8上,您不介意引入额外的依赖关系,请使用jOOλ及其iterateWhilePresent方法:
Seq.iterateWhilePresent(foo1, foo -> Optional.ofNullable(foo.getNext))
如果在JDK 8上并且您不想要引入额外的依赖关系,请编写一个使用自定义Spliterator
的方法,例如(请注意,这不是急切地调用generator
的最有效的实现):
public static <T> Stream<T> iterateUntilNull(T seed, UnaryOperator<T> generator) {
Spliterator<T> spliterator = new Spliterator<T>() {
private T next = seed;
@Override
public boolean tryAdvance(Consumer<? super T> action) {
if (next == null) {
return false;
}
action.accept(next);
next = generator.apply(next);
return true;
}
@Override
public Spliterator<T> trySplit() {
return null;
}
@Override
public long estimateSize() {
return Long.MAX_VALUE;
}
@Override
public int characteristics() {
return Spliterator.NONNULL;
}
};
return StreamSupport.stream(spliterator, false);
}
然后致电:
iterateUntilNull(foo1, Foo::getNext)