i am testing the new major update from Java A.K.A Java 8
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 a 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 dont understand.
the parameter from toIntFunction
is inferred or something
any help is hugely appreciate..
thanks a lot
Answer
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.