Java中的收益率回报率

Kas*_*dum 51 c# java linked-list

我使用泛型在java中创建了一个链表,现在我希望能够迭代列表中的所有元素.在C#中,我将yield return在链表中使用,同时浏览列表中包含的元素列表.

我如何创建上面的java版本,我可以迭代链表中包含的所有项目?

我希望能够编写代码ala

LinkedList<something> authors = new LinkedList<something>();
for (Iterator<something> i = authors.Values ; i.HasNext())
      doSomethingWith(i.Value);
Run Code Online (Sandbox Code Playgroud)

并且认为价值'属性'/方法将包含类似的代码

LinkedListObject<something> current = first;
While (current != null){
 yield return current.getValue();
 current = current.getNext()
}
Run Code Online (Sandbox Code Playgroud)

编辑:请注意,我对使用任何第三方API不感兴趣.仅内置java功能.

voi*_*tor 38

您可以返回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
                }

            };
        }
    };
}
Run Code Online (Sandbox Code Playgroud)


小智 26

"yield return"是一个非常复杂的编译器技巧.它基本上允许你声明性地实现IEnumerable,而没有任何令人烦恼的"搞清楚"如何构建迭代器的细节.不幸的是,它并没有很好地转换成其他语言,因为很少有编译器具有这样的能力.在某种程度上,"收益率回报"就像革命一样诅咒.

基本上在C#中,编译器将生成IEnumerable和IEnumerator(T)的两个实现.它通过基本上将"方法"的局部变量实现为生成的实现类中的实例字段以及检查包含"yield return"工件的帧来实现此目的.一旦你知道这一点,一个全面的开发人员应该有可能明确地完成同样的事情......虽然不是那么简洁.为了演示,我会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!
Run Code Online (Sandbox Code Playgroud)

如果你们都会原谅我的3AM伪java ...


Asa*_*sad 14

试试这个

查看本文以获取示例实现:


Cur*_*Dog 5

我不明白为什么人们在谈论线程......有什么我不知道的收益率回报?

据我所知,yield return只保存方法堆栈并在以后恢复它.要实现收益率返回,您只需手动保存状态.有关详细信息,请参阅Java迭代器类,但是对于链接列表,您只需保存当前项即可.对于数组,您只需要索引.

  • 这是对的。Yield 和 Yield return 在 C# 中不使用线程。他们进行编译时转换并创建一个状态机,但该状态机不使用任何额外的线程(尽管它可能是线程安全的)。 (2认同)