I am testing the new major update from Java (Java 8) and it is very interesting. I am using streams; in particular I am using this simple code.
private void getAvg()
{
final ArrayList<MyPerson>persons = new ArrayList<>
(Arrays.asList(new MyPerson("Ringo","Starr"),new MyPerson("John","Lennon"),new MyPerson("Paul","Mccartney"),new MyPerson("George","Harrison")));
final OptionalDouble average = persons.stream().filter(p->p.age>=40).mapToInt(p->p.age).average();
average.ifPresent(System.out::println);
return;
}
private class MyPerson
{
private final Random random = new Random();
private final String name,lastName;
private int age;
public MyPerson(String name,String lastName){this.name = name;this.lastName = lastName;this.age=random.nextInt(100);}
public MyPerson(String name,String lastName,final int age){this(name,lastName);this.age=age;}
public String getName(){return name;}
public String getLastName(){return lastName;}
public int getAge(){return age;}
}
In this example I understand very clear but later I have seen also can accomplish it in this way:
final OptionalDouble average = persons.stream().filter(p->p.age>=40)
.mapToInt(MyPerson::getAge).average();
average.ifPresent(System.out::println);
I have checked the method toIntFunction and in fact have the following signature:
@FunctionalInterface
public interface ToIntFunction<T> {
/**
* Applies this function to the given argument.
*
* @param value the function argument
* @return the function result
*/
int applyAsInt(T value);
}
As I can see the applyAsInt have a input and returns an int as long as I understand.
This code:
MyPerson::getAge
calls:
public int getAge(){return age;}//please correct me at this point
My question is: the method getAge
have not parameters and returns a int but the toIntFunction receive a parameter - this is the part I don't understand.
The parameter from toIntFunction
is inferred or something.
Remember a method reference is just a shortcut for a lambda. So an instance method reference is a lambda that calls that method on the argument. The type of the argument is the class given in the method reference. It helps to "unwrap" it.
MyPerson::getAge
Unwrap to a lambda:
(MyPerson p) -> p.getAge()
Unwrap to an anonymous class:
new ToIntFunction<MyPerson>() {
@Override
public int applyAsInt(MyPerson p) {
return p.getAge();
}
}
With a static method reference, the signature must match exactly, that is, the static method takes a T
and returns an int
. With an instance method reference, the parameter T
of the lambda is the object the method gets called on.
As far as I know MyPerson::getAge
is like a pointer to MyPerson
s getAge() method, which returns an int
. So value.getAge()
gets invoked in int applyAsInt(MyPerson value);
.
In other words: You just tell the stream, that it should use getAge()
s return value from it's current MyPerson
iteration variable to construct another collection an IntStream.
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