C# Java的收益率
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2352399/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Yield Return In Java
提问by Kasper Holdum
I've created a linked list in java using generics, and now I want to be able to iterate over all the elements in the list. In C# I would use yield return
inside the linked list while going over the list of elements contained in the list.
我已经使用泛型在 java 中创建了一个链表,现在我希望能够遍历列表中的所有元素。在 C# 中,我将yield return
在链表中使用,同时查看列表中包含的元素列表。
How would I go about creating a java version of the above where I can iterate over all the items contained in the linked list?
我将如何创建上述的 Java 版本,我可以在其中迭代链接列表中包含的所有项目?
I'm looking to be able to write code ala
我希望能够编写代码 ala
LinkedList<something> authors = new LinkedList<something>();
for (Iterator<something> i = authors.Values ; i.HasNext())
doSomethingWith(i.Value);
And was thinking that the Value 'property'/method would consist of code resembling
并且认为 Value 'property'/method 将包含类似的代码
LinkedListObject<something> current = first;
While (current != null){
yield return current.getValue();
current = current.getNext()
}
Edit: Notice that I'm not interested in using any 3rd party APIs. Built-in java functionality only.
编辑:请注意,我对使用任何 3rd 方 API 不感兴趣。仅内置 Java 功能。
采纳答案by crazyscot
Am I missing something here? There is already java.util.LinkedList, it is fully generics-enabled, and it has a method which returns an Iterator.
我在这里错过了什么吗?已经有 java.util.LinkedList,它完全支持泛型,并且有一个返回迭代器的方法。
If you really want to re-invent the wheel, I'd suggest you look into to creating a LinkedListIterator class, probably implementing ListIterator. It would remember its current position within the linked list and advance it on each successive call.
如果你真的想重新发明轮子,我建议你考虑创建一个 LinkedListIterator 类,可能实现 ListIterator。它会记住它在链表中的当前位置,并在每次连续调用时推进它。
回答by Asad
try this
尝试这个
check this article for a sample implementation as well:
还可以查看本文以获取示例实现:
回答by Denise
If you want the full functionality of yield return
, you probably need to set this up in two threads-- one for the first method, and one for the second. Then the first thread should wait
until the second thread puts its value somewhere accessible and notify
s it that it's ready. Then the first thread would process that value, wait
for the next value, etc.
如果您想要 的全部功能yield return
,您可能需要在两个线程中设置它——一个用于第一种方法,一个用于第二种方法。然后第一个线程应该wait
直到第二个线程将它的值放在可访问notify
的地方并且它已经准备好了。然后第一个线程将处理该值,wait
为下一个值等。
回答by CurtainDog
I don't understand why people are talking about threads... is there something I don't know about yield return?
我不明白为什么人们在谈论线程......关于收益率我有什么不知道的吗?
To my understanding yield return just saves the method stack and restores it at a later time. To implement yield return you just have to save the state manually. See the Java iterator classes for details, though for a linked list you can just get away with saving the current item. For an array you'd just need the index.
据我了解,yield return 只是保存方法堆栈并在以后恢复它。要实现收益回报,您只需手动保存状态。有关详细信息,请参阅 Java 迭代器类,但对于链接列表,您可以直接保存当前项目。对于数组,您只需要索引。
回答by Oren ZBM
Just to help readers understand the small details.
只是为了帮助读者了解小细节。
If you create a new list containing all the resulting elements and return the list, then this is a good implementation, simple enough to code. You can have as interesting data structure as you need, and when scanning it for the right entries, just return a list of all the matches, and your client will iterate on the list.
如果您创建一个包含所有结果元素的新列表并返回该列表,那么这是一个很好的实现,简单到可以编写代码。您可以根据需要拥有尽可能有趣的数据结构,并且在扫描它以查找正确的条目时,只需返回所有匹配项的列表,您的客户端将在列表上迭代。
If you want to save a state, it may be more complicated. You'll need to get to where you've been every time your function is called. Not to mention re-entrant issues, etc.
如果要保存状态,可能会更复杂。每次调用您的函数时,您都需要到达您去过的地方。更不用说重入问题等。
The solution with threads does not create a new list. And it is as simple as the first solution. The only issue is that you involve a thread synchronization which is a bit more hard to code, and has its performance penalties.
带有线程的解决方案不会创建新列表。它和第一个解决方案一样简单。唯一的问题是您涉及一个线程同步,这有点难以编码,并且会降低性能。
So, yes, yield return is great and is missing from Java. Yet there are workarounds.
所以,是的,yield 回报很好,Java 没有。不过还是有解决办法的。
回答by voidvector
You can return an anonymous implementation of Iterable. The effects are pretty pretty similar, just that this is a lot more verbose.
您可以返回 Iterable 的匿名实现。效果非常相似,只是这更冗长。
public Iterable<String> getStuff() {
return new Iterable<String>() {
@Override
public Iterator<String> iterator() {
return new Iterator<String>() {
@Override
public boolean hasNext() {
// TODO code to check next
}
@Override
public String next() {
// TODO code to go to next
}
@Override
public void remove() {
// TODO code to remove item or throw exception
}
};
}
};
}
回答by Garth Pickell
"yield return" is a very sophisticated compiler trick. It basically lets you declaratively implement IEnumerable without any of the annoying details of "figuring out" how to build your iterator. The unfortunate thing is that it does not translate into other languages well because very few compilers have such a capability. In some ways "yield return" is as damning as revolutionary.
“收益回报”是一个非常复杂的编译器技巧。它基本上允许您以声明方式实现 IEnumerable,而无需“弄清楚”如何构建迭代器的任何烦人的细节。不幸的是,它不能很好地翻译成其他语言,因为很少有编译器具有这种能力。在某些方面,“收益率”与革命性的一样可怕。
Basically in C#, the compiler will generate two implementations of IEnumerable and IEnumerator (of T). It does this by basically realizing your "method"'s local variables as instance fields in generated implementation classes as well as examining the frames containing a "yield return" artifact. Once you know this, it should be possible for a well rounded developer to accomplish the same thing explicitly... although not as concisely. To demonstrate, I will CONCAT!
基本上在 C# 中,编译器会生成 IEnumerable 和 IEnumerator (of T) 的两种实现。它通过基本上将“方法”的局部变量实现为生成的实现类中的实例字段以及检查包含“收益回报”工件的帧来实现这一点。一旦你知道了这一点,一个全面的开发人员应该有可能明确地完成同样的事情......虽然没有那么简洁。为了演示,我会CONCAT!
public static <T> Iterable<T> concat(Iterable<T> x, Iterable<T> y)
{
for(T e: x)
{
yield return e;
}
for(T e: y)
{
yield return e;
}
}
// becomes ....
public static <E> Iterator<E> concat_(Iterable<E> x, Iterator<E> y)
{
T e1, e2;
Iterator<E> i1, i2;
Iterator<E> s;
Iterator<E> s4 = new Iterator<E>()
{
public bool hasNext()
{
return false;
}
public E next()
{
throw ... ;
}
public void remove()
{
throw ... ;
}
}
Iterator<E> s3 = new Iterator<E>()
{
Iterator<E> act()
{
if(i2.hasNext())
{
return i2;
}
i2 = y.iterator();
return (s = s4);
}
public bool hasNext()
{
return act().hasNext();
}
public E next()
{
return act().next();
}
public void remove()
{
return i2.remove();
}
}
Iterator<E> s2 = new Iterator<E>()
{
Iterator<E> act()
{
if(i1.hasNext())
{
return i1;
}
i2 = y.iterator();
return (s = s3);
}
public bool hasNext()
{
return act().hasNext();
}
public E next()
{
return act().next();
}
public void remove()
{
return i1.remove();
}
};
Iterator<E> s1 = new Iterator<E>()
{
Iterator<E> act()
{
i1 = x.iterator();
return s = s2;
}
public bool hasNext()
{
return act().hasNext();
}
public E next()
{
return act().next();
}
public void remove()
{
return act().remove();
}
};
s = s1;
return new Iterator<T>()
{
public bool hasNext()
{
return s.hasNext();
}
public E next()
{
return s.next();
}
public void remove()
{
return s.remove();
}
};
}
public static <T> Iterable<T> concat(Iterable<T> x, Iterable<T> y)
{
return new Iterable<T>()
{
public Iterator<T> iterator()
{
return concat_(x, y)
}
};
}
// tada!
If you all will pardon my 3AM pseudo java...
如果你们都原谅我凌晨 3 点的伪 Java...
回答by Heiner Kuecker
use my java library to realize yield return without using threads or byte code manipulation
使用我的java库实现yield return而不使用线程或字节码操作
回答by sunneo
a yield return operation can be regarded as
收益率返回操作可以被视为
- put some checkpoint there
- write a value in somewhere
- when resume is acquired, jump to instruction next to it.
- 在那里放一些检查站
- 在某处写一个值
- 获取简历后,跳转到旁边的说明。
therefore I implement it as a state machine alike class, coroutine. within this mechanism, each instruction has its instruction pointer, index, and instruction may has a label along with it, so we can use jmp(label) to jump to the label.
因此我将它实现为类似状态机的类,协程。在这个机制中,每条指令都有它的指令指针、索引,并且指令可能有一个标签,所以我们可以使用 jmp(label) 跳转到标签。
- add some mechanism to achieve a goto syntax: addInstruction(..) and jmp()
- and store status/variable in somewhere: setVariable(name,value), yield(value)
- a way to temporarily suspend / resume: exec()
- 添加一些机制来实现 goto 语法:addInstruction(..) 和 jmp()
- 并将状态/变量存储在某处:setVariable(name,value), yield(value)
- 一种暂时挂起/恢复的方法:exec()
for example:
例如:
public class FibbonaciCoroutine implements Iterator<BigInteger> {
BigInteger[] bucket = { new BigInteger("1"), new BigInteger("1"), new BigInteger("0") };
int idx = 2;
Coroutine coroutine = new Coroutine((pthis) -> {
pthis.addInstruction("_label1", (me) -> {
int p1 = idx - 2;
int p2 = idx - 1;
if (p1 < 0)
p1 += 3;
if (p2 < 0)
p2 += 3;
bucket[idx] = bucket[p1].add(bucket[p2]);
idx = (idx + 1) % bucket.length;
me.yield(bucket[idx]);
});
// goto
pthis.addInstruction((me) -> {
me.jmp("_label1");
});
pthis.start();
});
@Override
public boolean hasNext() {
return !coroutine.isStopped();
}
@Override
public BigInteger next() {
while (coroutine.exec())
;
return coroutine.getYieldValue();
}
public static void main(String[] argv) {
FibbonaciCoroutine cor = new FibbonaciCoroutine();
for (int i = 0; i < 100 && cor.hasNext(); ++i) {
System.out.printf("%d ", cor.next());
}
}
}