Java 是否有相当于 C# 的“yield”?关键词?
我知道 Java 本身没有直接的等价物,但也许有第三方?
真的很方便。目前我想实现一个迭代器,它生成树中的所有节点,大约有五行带有yield的代码。
I know there is no direct equivalent in Java itself, but perhaps a third party?
It is really convenient. Currently I'd like to implement an iterator that yields all nodes in a tree, which is about five lines of code with yield.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
我知道的两个选项是 Aviad Ben Dov 2007 年的 infomancers-collections 库 和 < a href="http://svn.jimblackler.net/jimblackler/trunk/IdeaProjects/YieldAdapter/" rel="noreferrer">Jim Blackler 2008 年的 YieldAdapter 库(另一个答案中也提到了)。
两者都允许您在 Java 中使用类似
yield return
的结构编写代码,因此两者都能满足您的要求。两者之间的显着差异是:Mechanics
Aviad 的库使用字节码操作,而 Jim 的库使用多线程。根据您的需求,每种方法可能都有自己的优点和缺点。 Aviad 的解决方案可能更快,而 Jim 的解决方案更便携(例如,我认为 Aviad 的库不适用于 Android)。
Interface
Aviad 的库有一个更清晰的界面 - 这里有一个例子:
而 Jim 的则复杂得多,需要您
adept
一个通用的Collector
,它有一个collect(ResultHandler)
方法...呃。但是,您可以使用类似于 Zoom Information 提供的 Jim 代码包装器,这大大简化了:
Aviad 的解决方案是 BSD。
Jim 的解决方案是公共领域的,上面提到的它的包装器也是公共领域的。
The two options I know of is Aviad Ben Dov's infomancers-collections library from 2007 and Jim Blackler's YieldAdapter library from 2008 (which is also mentioned in the other answer).
Both will allow you to write code with
yield return
-like construct in Java, so both will satisfy your request. The notable differences between the two are:Mechanics
Aviad's library is using bytecode manipulation while Jim's uses multithreading. Depending on your needs, each may have its own advantages and disadvantages. It's likely Aviad's solution is faster, while Jim's is more portable (for example, I don't think Aviad's library will work on Android).
Interface
Aviad's library has a cleaner interface - here's an example:
While Jim's is way more complicated, requiring you to
adept
a genericCollector
which has acollect(ResultHandler)
method... ugh. However, you could use something like this wrapper around Jim's code by Zoom Information which greatly simplifies that:License
Aviad's solution is BSD.
Jim's solution is public domain, and so is its wrapper mentioned above.
现在 Java 有了 Lambda,这两种方法都可以变得更加简洁。您可以执行类似
我在这里解释了更多内容的操作。
Both of these approaches can be made a bit cleaner now Java has Lambdas. You can do something like
I explained a bit more here.
我知道这是一个非常老的问题,上面描述了两种方法:
yield
显然会产生资源成本。然而,还有另一种(第三种,可能是最自然的)方法在 Java 中实现
yield
生成器,它是最接近 C# 2.0+ 编译器对yield return/break< 的实现。 /code> 生成:lombok-pg。它完全基于状态机,需要与 javac 紧密配合来操作源代码 AST。不幸的是,lombok-pg 支持似乎已停止(超过一两年没有存储库活动),并且原始的 Project Lombok 遗憾的是缺少
yield
功能(不过它有更好的 IDE,如 Eclipse、IntelliJ IDEA 支持)。I know it's a very old question here, and there are two ways described above:
yield
that obviously has resource costs.However, there is another, the third and probably the most natural, way of implementing the
yield
generator in Java that is the closest implementation to what C# 2.0+ compilers do foryield return/break
generation: lombok-pg. It's fully based on a state machine, and requires tight cooperation withjavac
to manipulate the source code AST. Unfortunately, the lombok-pg support seems to be discontinued (no repository activity for more than a year or two), and the original Project Lombok unfortunately lacks theyield
feature (it has better IDE like Eclipse, IntelliJ IDEA support, though).我刚刚发布了另一个(麻省理工学院许可的)解决方案此处,它在单独的线程中启动生产者,并且在生产者和消费者之间设置一个有界队列,允许生产者和消费者之间进行缓冲、流量控制和并行流水线(以便消费者可以在生产者致力于生产下一个项目时消耗前一个项目) 。
您可以使用这个匿名内部类形式:
例如:
或者您可以使用 lambda 表示法来减少样板代码:
I just published another (MIT-licensed) solution here, which launches the producer in a separate thread, and sets up a bounded queue between the producer and the consumer, allowing for buffering, flow control, and parallel pipelining between producer and consumer (so that the consumer can be working on consuming the previous item while the producer is working on producing the next item).
You can use this anonymous inner class form:
for example:
Or you can use lambda notation to cut down on boilerplate:
Stream.iterate(seed, SeedOperator).limit(n).foreach(action) 与yield 运算符不同,但以这种方式编写自己的生成器可能很有用:
Stream.iterate(seed, seedOperator).limit(n).foreach(action) is not the same as yield operator, but it may be usefull to write your own generators this way:
我还建议您是否已经在项目中使用 RXJava 将 Observable 用作“屈服者”。如果您制作自己的 Observable,则可以以类似的方式使用它。
可观察量可以转换为迭代器,因此您甚至可以在更传统的 for 循环中使用它们。 RXJava 还为您提供了非常强大的工具,但如果您只需要一些简单的东西,那么这可能有点过大了。
I'd also suggest if you're already using RXJava in your project to use an Observable as a "yielder". It can be used in a similar fashion if you make your own Observable.
Observables can be transformed into iterators so you can even use them in more traditional for loops. Also RXJava gives you really powerful tools, but if you only need something simple then maybe this would be an overkill.
从这里。
From here.
我编写了一个新的 库,它实现了 Java 生成器。它简单、无线程且快速。
下面是生成无限斐波那契数的示例:
Seq
接口就像 JavaStream
和 KotlinSequence
一样,但比它们都快。在这里,让我们打印斐波那契数列的前 7 个元素
对于最初的问题,生成树的所有节点?一根线就够了。
I wrote a new library that has implemented generator for Java. It's simple, thread-free and fast.
Here is an example of generating endless fibonacci numbers:
The
Seq
interface is just like JavaStream
and KotlinSequence
, but faster than all of them.Here, let's print the first 7 elements of the fibonacci series
For the original problem, yielding all nodes of a tree? One line is enough.
是的,你可以在 Java 中使用类似 Yield Return 的语法!
在java中,要获得这样的语法:
创建一个这样的类:
其中f.accept() 履行yield return 的作用。
Yes, you can have yield return like syntax in Java!
In java, to gain syntax like:
One creates a class like this:
Where f.accept() fulfills the role of yield return.
下面介绍了如何将具有 Yield 逻辑的代码转换为 Java 等效代码。它可能需要一些努力,但至少不需要第三方库(仍然需要对 lambda 的支持):
C# :
Java :
Here is how to convert code with yield logic to Java equivalent. It might require some effort but at least there is no need of a third party library (still, it require support for lambdas):
C# :
Java :