I was exploring the Java 8 source and found this particular part of code very surprising:
//defined in IntPipeline.java
@Override
public fin
This is a method reference in Java 8. The oracle documentation is here.
As stated in the documentation...
The method reference Person::compareByAge is a reference to a static method.
The following is an example of a reference to an instance method of a particular object:
class ComparisonProvider {
public int compareByName(Person a, Person b) {
return a.getName().compareTo(b.getName());
}
public int compareByAge(Person a, Person b) {
return a.getBirthday().compareTo(b.getBirthday());
}
}
ComparisonProvider myComparisonProvider = new ComparisonProvider();
Arrays.sort(rosterAsArray, myComparisonProvider::compareByName);
The method reference myComparisonProvider::compareByName invokes the method compareByName that is part of the object myComparisonProvider. The JRE infers the method type arguments, which in this case are (Person, Person).
In java-8 Streams Reducer in simple works is a function which takes two values as input and returns result after some calculation. this result is fed in next iteration.
in case of Math:max function, method keeps returning max of two values passed and in the end you have largest number in hand.
At runtime they behave a exactly the same.The bytecode may/not be same (For above Incase,it generates the same bytecode(complie above and check javaap -c;))
At runtime they behave a exactly the same.method(math::max);,it generates the same math (complie above and check javap -c;))
return reduce(Math::max);
is NOT EQUAL to return reduce(max());
But it means, something like this:
IntBinaryOperator myLambda = (a, b)->{(a >= b) ? a : b};//56 keystrokes I had to type -_-
return reduce(myLambda);
You can just save 47 keystrokes if you write like this
return reduce(Math::max);//Only 9 keystrokes ^_^
In older Java versions, instead of "::" or lambd, you can use:
public interface Action {
void execute();
}
public class ActionImpl implements Action {
@Override
public void execute() {
System.out.println("execute with ActionImpl");
}
}
public static void main(String[] args) {
Action action = new Action() {
@Override
public void execute() {
System.out.println("execute with anonymous class");
}
};
action.execute();
//or
Action actionImpl = new ActionImpl();
actionImpl.execute();
}
Or passing to the method:
public static void doSomething(Action action) {
action.execute();
}
Usually, one would call the reduce
method using Math.max(int, int)
as follows:
reduce(new IntBinaryOperator() {
int applyAsInt(int left, int right) {
return Math.max(left, right);
}
});
That requires a lot of syntax for just calling Math.max
. That's where lambda expressions come into play. Since Java 8 it is allowed to do the same thing in a much shorter way:
reduce((int left, int right) -> Math.max(left, right));
How does this work? The java compiler "detects", that you want to implement a method that accepts two int
s and returns one int
. This is equivalent to the formal parameters of the one and only method of interface IntBinaryOperator
(the parameter of method reduce
you want to call). So the compiler does the rest for you - it just assumes you want to implement IntBinaryOperator
.
But as Math.max(int, int)
itself fulfills the formal requirements of IntBinaryOperator
, it can be used directly. Because Java 7 does not have any syntax that allows a method itself to be passed as an argument (you can only pass method results, but never method references), the ::
syntax was introduced in Java 8 to reference methods:
reduce(Math::max);
Note that this will be interpreted by the compiler, not by the JVM at runtime! Although it produces different bytecodes for all three code snippets, they are semantically equal, so the last two can be considered to be short (and probably more efficient) versions of the IntBinaryOperator
implementation above!
(See also Translation of Lambda Expressions)