【问题标题】:Lambda expression in Iterable implementationIterable 实现中的 Lambda 表达式
【发布时间】:2015-03-08 22:49:43
【问题描述】:

所以我有我朋友给我看的这段代码,我必须承认我不明白发生了什么。我了解有关 lamba 表达式的概念,并且在 haskell 中编写了很多,但到目前为止还没有在 Java 中编写。

让我困惑的是编译器如何知道我认为是 lambda 的函数应该是 Iterable 接口中所需的“iterator()”。

public Iterable<V> values() {
    return () -> {
        return new Iterator<V>() {
            private Iterator<TableEntry<K, V>> iter = iterator();

            @Override
            public boolean hasNext() {
                return iter.hasNext();
            }

            @Override
            public V next() {
                return iter.next().getValue();
            }
        };
    };
}

我有我的版本,但是我有一个阴影问题,我为实现 Iterable 值而制作的 iterator() 在其内部被调用,导致堆栈溢出。我想要的是使用在 values() 范围内定义但不知道如何指向它的 iterator()。

public Iterable<V> values() {
    return new ValuesIterable<V>();
}

public class ValuesIterable<V> implements Iterable<V>{
    public Iterator<V> iterator() {
        return new ValuesIterator();
    }

    public class ValuesIterator implements Iterator<V>
    {
        Iterator<SimpleHashtable.TableEntry<K, V>> iter = (Iterator<TableEntry<K, V>>) iterator();

        public boolean hasNext()
        {
            return iter.hasNext();
        }

        public V next()
        {
            return iter.next().getValue();
        }

        public void remove()
        {
            return;
        }
    }
}

注意:这个iterator()是在variables()的范围内

public Iterator<SimpleHashtable.TableEntry<K, V>> iterator() {
    return new TableEntryIterator();
}

【问题讨论】:

    标签: java lambda java-8 iterable shadowing


    【解决方案1】:

    Lambda 表达式用于实现函数式接口,其中只有一种方法需要实现。因此,由于您的values() 方法返回Iterable&lt;V&gt;,lambda 表达式必须实现该接口的单一方法,即iterator()

    至于您示例中 lambda 表达式的语法:

    空括号()表示lambda表达式实现的方法没有参数,iterator()方法确实如此。

    -&gt; 之后是 lambda 表达式的主体,在此示例中,它返回实现 Iterator&lt;V&gt; 接口的匿名类的实例。

    哦,您的第二个代码 sn-p 导致堆栈溢出,因为您的 iterator() 方法创建了一个 ValuesIterator 的实例,并且作为实例初始化的一部分,您调用了该 iterator() 方法,导致无限递归。

    【讨论】:

    • 你能澄清一下这个特定用法背后的语法吗?
    • 感谢您的简短而完整的回答 :)
    • “在这个例子中返回一个匿名类的实例” 这是误导。编译器不太可能生成传统意义上的匿名类。通常,lambda 让 Java 开发人员可以访问 invokedynamic
    • @McDowell 虽然 lambda 表达式确实如此,但问题中的 lambda 表达式主体显式创建了一个匿名类实例 - new Iterator&lt;V&gt;() {...
    • @Eran 啊,我的错,我看错了你的答案。你是对的。
    猜你喜欢
    • 2023-03-28
    • 2018-01-20
    • 2015-07-03
    • 1970-01-01
    • 2018-01-25
    • 1970-01-01
    • 1970-01-01
    • 2014-10-09
    • 2013-07-02
    相关资源
    最近更新 更多