@FunctionalInterface
public interface Streamable<T> extends Iterable<T>, Supplier<Stream<T>>
I was exploring the Streamable Interface and the first method that I came across was the empty()
method that has the following definition.
static <T> Streamable<T> empty() {
return Collections::emptyIterator;
}
Collections::emptyIterator
returns the Iterator<T>
but the return type of this method is Streamable<T>
. Streamble extends Iterable and Supplier and not Iterator interface.
I didn't understand how is that working fine. Can someone please help me in understanding this?
I'm just failing in understanding the concept here. I wanted to know how is this working as I'm aware of how Inheritance works, but I'm unable to figure it out. I think I'm missing something here.
empty()
returns a method reference Collections::emptyIterator
.
In order for this code to pass compilation, that method reference must conform with the single abstract method of the Streamable<>
interface.
Collections
's emptyIterator()
takes no arguments and returns an Iterator<T>
.
Streamable<>
extends both Iterable<T>
and Supplier<Stream<T>>
, which means it has to implement two methods (iterator()
and get()
), but one of them cannot be abstract (otherwise it wouldn't be a functional interface).
Collections
's emptyIterator()
can conform with Iterable<T>
's Iterator<T> iterator()
signature.
So if Streamable<T>
has a default implementation of Supplier<Stream<T>>
's get()
method (if it doesn't, Streamable<T>
cannot be a functional interface), Collections::emptyIterator
can implement the Streamable<T>
interface.
EDIT: If you were referring to org.springframework.data.util.Streamable, you can see that it does have a default implementation of get()
:
/*
* (non-Javadoc)
* @see java.util.function.Supplier#get()
*/
default Stream<T> get() {
return stream();
}
Hence, any method reference that conforms with the single abstract method Iterator<T> iterator()
, can implement that interface. Therefore Collections::emptyIterator
can implement Streamable<T>
.
For the record, this is the fully qualified name : org.springframework.data.util.Streamable
.
The thing is that in the current context :
static <T> Streamable<T> empty() {
return Collections.emptyIterator();
}
is not the same thing than :
static <T> Streamable<T> empty() {
return Collections::emptyIterator;
}
return Collections.emptyIterator()
returns an Iterator
object while the method expects a Streamable
. That indeed cannot compile as you supposed.
But return Collections::emptyIterator
doesn't return an Iterator
object. Instead, it defines the lambda body associated to the Streamable
functional interface object returned by empty()
.
In fact this method reference :
return Collections::emptyIterator;
is equivalent to :
return () -> Collections.emptyIterator();
Why is it valid ?
Because Streamable
is a functional interface defined as a function : ()-> Iterator<T>
and emptyIterator()
returns Iterator<T>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With