我知道Java本身没有直接的等价物,但也许是第三方?
真的很方便。目前我想实现一个迭代器,它产生一个树中的所有节点,这是大约五行带有yield的代码。
我所知道的两个选项是Aviad Ben Dov's infomancers-collections library from 2007和Jim Blackler's YieldAdapter library from 2008(在另一个答案中也提到了)。
两者都允许您使用Java中的yield return
类构造编写代码,因此两者都将满足您的请求。两者之间的显着差异是:
当Jim使用多线程时,Aviad的库正在使用字节码操作。根据您的需要,每个人都有自己的优点和缺点。可能Aviad的解决方案更快,而Jim更便携(例如,我不认为Aviad的库可以在Android上运行)。
Aviad的库有一个更干净的界面 - 这是一个例子:
Iterable<Integer> it = new Yielder<Integer>() {
@Override protected void yieldNextCore() {
for (int i = 0; i < 10; i++) {
yieldReturn(i);
if (i == 5) yieldBreak();
}
}
};
虽然吉姆是更复杂的,要求你adept
一个通用的Collector
有一个collect(ResultHandler)
方法......呃。但是,你可以使用类似this wrapper around Jim's code by Zoom Information的东西,这大大简化了:
Iterable<Integer> it = new Generator<Integer>() {
@Override protected void run() {
for (int i = 0; i < 10; i++) {
yield(i);
if (i == 5) return;
}
}
};
带有BDS的Aviadus解决方案。
Jim的解决方案是公共领域,上面提到的包装器也是如此。
现在,Java拥有Lambdas,这两种方法都可以变得更加清晰。你可以做点什么
public Yielderable<Integer> oneToFive() {
return yield -> {
for (int i = 1; i < 10; i++) {
if (i == 6) yield.breaking();
yield.returning(i);
}
};
}
我知道这是一个非常古老的问题,上面介绍了两种方法:
yield
显然有资源成本。然而,在Java中实现yield
生成器还有另一种,第三种也许是最自然的方式,它是C#2.0+编译器为yield return/break
生成所做的最接近的实现:lombok-pg。它完全基于状态机,并且需要与javac
紧密合作来操纵源代码AST。不幸的是,lombok-pg支持似乎已停止(一年或两年没有存储库活动),原来的Project Lombok不幸缺乏yield
功能(它有更好的IDE,如Eclipse,IntelliJ IDEA支持)。
Stream.iterate(seed,seedOperator).limit(n).foreach(action)与yield运算符不同,但以这种方式编写自己的生成器可能很有用:
import java.util.stream.Stream;
public class Test01 {
private static void myFoo(int someVar){
//do some work
System.out.println(someVar);
}
private static void myFoo2(){
//do some work
System.out.println("some work");
}
public static void main(String[] args) {
Stream.iterate(1, x -> x + 1).limit(15).forEach(Test01::myFoo); //var1
Stream.iterate(1, x -> x + 1).limit(10).forEach(item -> myFoo2()); //var2
}
}
我还建议你是否已经在项目中使用RXJava将Observable用作“yielder”。如果你制作自己的Observable,它可以以类似的方式使用。
public class Example extends Observable<String> {
public static void main(String[] args) {
new Example().blockingSubscribe(System.out::println); // "a", "b", "c", "d"
}
@Override
protected void subscribeActual(Observer<? super String> observer) {
observer.onNext("a"); // yield
observer.onNext("b"); // yield
observer.onNext("c"); // yield
observer.onNext("d"); // yield
observer.onComplete(); // finish
}
}
可以将Observable转换为迭代器,这样您甚至可以在更传统的for循环中使用它们。此外,RXJava为您提供了非常强大的工具,但如果您只需要简单的东西,那么这可能是一种过度杀伤力。
在Java 8中,您可以使用:Stream.of