Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lambda expression in Iterable implementation

So I have this piece of code my friend showed me and I must admit I do not understand what is going on. I understand the concept around lamba expressions and have written quite a few of them in haskell but none in Java so far.

What confuses me is how does the compiler know that the function which I supposed is lambdaed is supposed to be the "iterator()" one required in the Iterable interface.

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();
            }
        };
    };
}

I have my version of this but I have a problem with shadowing where the iterator() I make to implement Iterable for values is called inside itself causing stack overflow. What I want is to use the iterator() which is defined in the scope of the values() but don't know how to point to it.

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;
        }
    }
}

note: this iterator() is in the scope of variables()

public Iterator<SimpleHashtable.TableEntry<K, V>> iterator() {
    return new TableEntryIterator();
}
like image 700
ditoslav Avatar asked Jan 10 '15 19:01

ditoslav


1 Answers

Lambda expressions are used to implement functional interfaces, in which there is only one method that requires implementation. Therefore, since your values() method returns Iterable<V>, the lambda expression must implement the single method of that interface, which is iterator().

As for the syntax of the lambda expression in your example :

The empty brackets () mean that the method implemented by the lambda expression has no arguments, which is indeed true for the iterator() method.

After the ->, you have the body of the lambda expression, which in this example returns an instance of an anonymous class that implements the Iterator<V> interface.

Oh, and your second code snippet causes stack overflow because your iterator() method creates an instance of ValuesIterator, and as part of the initialization of the instance, you call that iterator() method, causing an infinite recursion.

like image 72
Eran Avatar answered Oct 28 '22 08:10

Eran