I know how the lambda expresion works and I know it is an argument for .filter()
that establish the criteria to filter with. But I don’t get how .filter()
uses the argument, in this case a lambda expression, because .filter() does’t have an implementation or at least require one at compile time. I search for this unknown implementation in the Oracle’s site but there are just a few words explaning how it works and no code at all.
Is that implemetation hidden or is created automatically by the java compiler?
Does an aggregate operation need one?
double average = roster
.stream()
.filter(p -> p.getGender() == Person.Sex.MALE)
.mapToInt(Person::getAge)
.average()
.getAsDouble();
roster
is a List<Person>
instance of ArrayList<Person>
Person
is a simple class that represents a person
The lambda object is created automatically by the compiler.
Any “functional” interface (that is an interface with just 1 function) can be the target for one. The equivalent non-lambda code would be:
double average = roster
.stream()
.filter(new Predicate<Person>(){
public boolean test(Person p){
return p.getGender() == Person.Sex.MALE;
}
})
.mapToInt(Person::getAge)
.average()
.getAsDouble();
And it could have been implemented this way by the compiler but they were concerned with efficiency and wanted people to be able to reference methods directly. So instead they translate the lambda to a private method which may or may not be static (depending on whether this
is captured) and use a meta factory that creates the actual lambda object which then forwards to the actual code in the private method.
For more information see the following page.
2
The Collection interface now has a default method that implements the stream()
method that returns the stream. Default methods are new to Java 8 and allow for interfaces to implement methods in order to evolve the API. So this implementation of the stream()
method on the Collection must be constructing an object that implements the Stream interface and returns it.
Internally, the Collection interface method stream()
forwards a call to the StreamSupport class that is documented. The SteamSupport class in turn constructs an undocumented class called ReferencePipeline that you can find in the java source code in the java 8 JDK.
So, apparently it is the intention of the API designer that if you want to do some custom stream stuff you would go no further than the StreamSupport class.
0