Method
reference allows you to refer constructors or methods without executing them.
You can access a method (or) constructor using :: notation. The only condition is
that the methods should be assignable to any Functional Interface.
For example
first I am going to explain following application using lambda expression, next
same application rewritten using method references.
Following
application
a.
Display
all employees whose age is > 27.
b. Display all employees whose firstName starts with ‘S’.
b. Display all employees whose firstName starts with ‘S’.
import java.util.Objects; public class Employee { private int id; private String firstName; private String lastName; private int age; private String city; private double salary; public Employee(int id, String firstName, String lastName, int age, String city, double salary) { super(); this.id = id; this.firstName = firstName; this.lastName = lastName; this.age = age; this.city = city; this.salary = salary; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } @Override public boolean equals(Object employee) { if (Objects.isNull(employee)) return false; if (!(employee instanceof Employee)) return false; Employee emp = (Employee) employee; return id == emp.id; } @Override public int hashCode() { return Objects.hash(id, firstName, lastName, age); } @Override public String toString() { return String.format("%s(%s,%d,%f)", firstName, city, age, salary); } }
import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; public class EmployeeTest { public static <T> List<T> processEmployees(List<T> employees, Predicate<T> predicate) { List<T> tmpList = new ArrayList<>(); for (T emp : employees) { if (predicate.test(emp)) { tmpList.add(emp); } } return tmpList; } public static void main(String args[]) { Employee emp1 = new Employee(1, "Hari Krishna", "Gurram", 26, "Bangalore", 40000); Employee emp2 = new Employee(2, "Joel", "Chelli", 27, "Hyderabad", 50000); Employee emp3 = new Employee(3, "Shanmukh", "Kummary", 28, "Chennai", 35000); Employee emp4 = new Employee(4, "Harika", "Raghuram", 27, "Chennai", 76000); Employee emp5 = new Employee(5, "Sudheer", "Ganji", 27, "Bangalore", 90000); Employee emp6 = new Employee(6, "Rama Krishna", "Gurram", 27, "Bangalore", 56700); Employee emp7 = new Employee(7, "PTR", "PTR", 27, "Hyderabad", 123456); Employee emp8 = new Employee(8, "Siva krishna", "Ponnam", 28, "Hyderabad", 98765); List<Employee> employees = new ArrayList<>(); employees.add(emp1); employees.add(emp2); employees.add(emp3); employees.add(emp4); employees.add(emp5); employees.add(emp6); employees.add(emp7); employees.add(emp8); List<Employee> ageGreat27; List<Employee> firstNameStartsWithS; ageGreat27 = processEmployees(employees, (emp) -> emp.getAge() > 27); firstNameStartsWithS = processEmployees(employees, (emp) -> emp .getFirstName().startsWith("S")); System.out.println(ageGreat27); System.out.println(firstNameStartsWithS); } }
Output
[Shanmukh(Chennai,28,35000.000000), Siva krishna(Hyderabad,28,98765.000000)] [Shanmukh(Chennai,28,35000.000000), Sudheer(Bangalore,27,90000.000000), Siva krishna(Hyderabad,28,98765.000000)]
public
static <T> List<T> processEmployees(List<T>
employees,Predicate<T> predicate) {
List<T> tmpList = new
ArrayList<>();
for (T emp : employees) {
if (predicate.test(emp)) {
tmpList.add(emp);
}
}
return tmpList;
}
Above method
takes list of objects, predicate as input and check whether an object matches
given predicate or not. If an object satisfies given predicate, it is added to
list else not.
ageGreat27 = processEmployees(employees, (emp)
-> emp.getAge() > 27);
Above
statement list all employees whose age is > 27.
firstNameStartsWithS = processEmployees(employees,
(emp) -> emp.getFirstName().startsWith("S"));
Above
statement list all employees whose first name starts with S.
Same
application can be rewritten using method references like following.
import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; public class EmployeeTest { public static boolean isAgeGreat27(Employee emp) { return emp.getAge() > 27; } public static boolean isNameStartsWithS(Employee emp) { return emp.getFirstName().startsWith("S"); } public static <T> List<T> processEmployees(List<T> employees, Predicate<T> predicate) { List<T> tmpList = new ArrayList<>(); for (T emp : employees) { if (predicate.test(emp)) { tmpList.add(emp); } } return tmpList; } public static void main(String args[]) { Employee emp1 = new Employee(1, "Hari Krishna", "Gurram", 26, "Bangalore", 40000); Employee emp2 = new Employee(2, "Joel", "Chelli", 27, "Hyderabad", 50000); Employee emp3 = new Employee(3, "Shanmukh", "Kummary", 28, "Chennai", 35000); Employee emp4 = new Employee(4, "Harika", "Raghuram", 27, "Chennai", 76000); Employee emp5 = new Employee(5, "Sudheer", "Ganji", 27, "Bangalore", 90000); Employee emp6 = new Employee(6, "Rama Krishna", "Gurram", 27, "Bangalore", 56700); Employee emp7 = new Employee(7, "PTR", "PTR", 27, "Hyderabad", 123456); Employee emp8 = new Employee(8, "Siva krishna", "Ponnam", 28, "Hyderabad", 98765); List<Employee> employees = new ArrayList<>(); employees.add(emp1); employees.add(emp2); employees.add(emp3); employees.add(emp4); employees.add(emp5); employees.add(emp6); employees.add(emp7); employees.add(emp8); List<Employee> ageGreat27; List<Employee> firstNameStartsWithS; ageGreat27 = processEmployees(employees, EmployeeTest::isAgeGreat27); firstNameStartsWithS = processEmployees(employees, EmployeeTest::isNameStartsWithS); System.out.println(ageGreat27); System.out.println(firstNameStartsWithS); } }
Output
[Shanmukh(Chennai,28,35000.000000), Siva krishna(Hyderabad,28,98765.000000)] [Shanmukh(Chennai,28,35000.000000), Sudheer(Bangalore,27,90000.000000), Siva krishna(Hyderabad,28,98765.000000)]
1. ageGreat27 = processEmployees(employees,
(emp) -> emp.getAge() > 27);
Above
statement is equivalent to following statement.
ageGreat27 = processEmployees(employees,
EmployeeTest::isAgeGreat27);
In simple
terms, method reference is a shorthand form of lambda expressions.
(emp) -> emp.getAge()
Is equivalent
to
Employee::getAge
Remember
parenthesis are not needed after method name, since we are not calling the
method, we are just referring it.
public static boolean isAgeGreat27(Employee emp) {
return
emp.getAge() > 27;
}
2. firstNameStartsWithS =
processEmployees(employees, (emp) ->
emp.getFirstName().startsWith("S"));
Above
statement is equivalent to following statement.
firstNameStartsWithS =
processEmployees(employees,EmployeeTest::isNameStartsWithS);
public static boolean isNameStartsWithS(Employee
emp) {
return
emp.getFirstName().startsWith("S");
}
"EmployeeTest::isNameStartsWithS"
statement refers the method isNameStartsWithS of class EmployeeTest.
Kinds of method references
There are
four kinds of method references.
Kind Of reference
|
Example
|
Reference
to a static method
|
ContainingClass::staticMethodName
|
Reference
to an instance method of a particular object
|
containingObject::instanceMethodName
|
Reference
to an instance method of an arbitrary object of a particular type
|
ContainingType::methodName
|
Reference
to a constructor
|
ClassName::new
|
Previous
application is an example of Reference to a static method.
Reference to an instance method of a particular
object
Following
example illustrate the use of how to refer an instance method of particular
object.
public class EmployeeComparator { public int compareByFirstName(Employee emp1, Employee emp2) { return emp1.getFirstName().compareTo(emp2.getFirstName()); } public int compareBySalary(Employee emp1, Employee emp2) { return (int) (emp1.getSalary() - emp2.getSalary()); } }
import java.util.ArrayList; import java.util.List; public class SortEmployee { public static void main(String args[]) { Employee emp1 = new Employee(1, "Hari Krishna", "Gurram", 26, "Bangalore", 40000); Employee emp2 = new Employee(2, "Joel", "Chelli", 27, "Hyderabad", 35000); Employee emp3 = new Employee(3, "Shanmukh", "Kummary", 28, "Chennai", 76000); Employee emp4 = new Employee(4, "Harika", "Raghuram", 27, "Chennai", 75000); Employee emp5 = new Employee(5, "Sudheer", "Ganji", 27, "Bangalore", 90000); Employee emp6 = new Employee(6, "Rama Krishna", "Gurram", 27, "Bangalore", 100000); Employee emp7 = new Employee(7, "PTR", "PTR", 27, "Hyderabad", 200000); Employee emp8 = new Employee(8, "Siva krishna", "Ponnam", 28, "Hyderabad", 55000); List<Employee> employees = new ArrayList<>(); employees.add(emp1); employees.add(emp2); employees.add(emp3); employees.add(emp4); employees.add(emp5); employees.add(emp6); employees.add(emp7); employees.add(emp8); EmployeeComparator comparisonProvider = new EmployeeComparator(); System.out.println("Sort employees by first name"); employees.sort(comparisonProvider::compareByFirstName); System.out.println(employees); System.out.println("\nSort employees by salary"); employees.sort(comparisonProvider::compareBySalary); System.out.println(employees); } }
Output
Sort employees by first name [Hari Krishna(Bangalore,26,40000.000000), Harika(Chennai,27,75000.000000), Joel(Hyderabad,27,35000.000000), PTR(Hyderabad,27,200000.000000), Rama Krishna(Bangalore,27,100000.000000), Shanmukh(Chennai,28,76000.000000), Siva krishna(Hyderabad,28,55000.000000), Sudheer(Bangalore,27,90000.000000)] Sort employees by salary [Joel(Hyderabad,27,35000.000000), Hari Krishna(Bangalore,26,40000.000000), Siva krishna(Hyderabad,28,55000.000000), Harika(Chennai,27,75000.000000), Shanmukh(Chennai,28,76000.000000), Sudheer(Bangalore,27,90000.000000), Rama Krishna(Bangalore,27,100000.000000), PTR(Hyderabad,27,200000.000000)]
Reference to an Instance Method of an Arbitrary
Object of a Particular Type
Following
example illustrate the use of how to refer an arbitrary Object of a Particular
Type.
import java.util.Arrays; public class Test { public static void main(String args[]) { String[] stringArray = { "Kiran", "Kumar", "Hari", "Krishna", "Gopi", "Battu", "Sudheer", "Rama" }; Arrays.sort(stringArray, String::compareToIgnoreCase); for (String s : stringArray) { System.out.println(s); } } }
Output
Battu Gopi Hari Kiran Krishna Kumar Rama Sudheer
Reference to a constructor
You can
reference a constructor in the same way as a static method by using the name
new.
import java.util.*; public class Test { public interface CollectionFactory<T> { T get(); } public static <T> T getCollection(CollectionFactory<T> collectionFactory) { return collectionFactory.get(); } public static void main(String args[]) { Set<String> hashSet1 = getCollection(() -> (new HashSet<String>())); Map<String, String> hashmap1 = getCollection(() -> (new HashMap<String, String>())); /* Above statements can be written using lambda expressions like below */ Set<String> hashSet2 = getCollection(HashSet<String>::new); Map<String, String> hashmap2 = getCollection(HashMap<String, String>::new); System.out.println(hashSet1 instanceof HashSet); System.out.println(hashmap1 instanceof HashMap); System.out.println(hashSet2 instanceof HashSet); System.out.println(hashmap2 instanceof HashMap); } }
Output
true true true true
When you cannot use Method reference?
You cannot
pass arguments to the method reference.
When I can use method reference?
When a
Lambda expression is invoking already defined method, you can replace it with reference
to that method.
No comments:
Post a Comment