Site Search:

Use method references with Streams

<Back

method::reference
method::reference


If an interface has only one abstract method, it can be turned into functional interface. The calling code can pass in a lambda expression as the implementation of the functional interface.

If the lambda expression do nothing but calls one method/function, we are actually dealing with the named function. The lambda expression can be even shorter. Java 8 added syntax supporting for it -- you can now reference a function with class/objectname::functionname, which is not an object reference, and can only be assigned to functional interface.

There are 4 types of method references.

  1. Reference to a static method -- class-name::static-method-name.
  2. Reference to an instance method of an arbitrary object -- class-name::instance-method-name
  3. Reference to an instance method of a particular object -- object-name::instance-method-name
  4. Reference to a constructor -- class-name::new


OCPJP>cat MethodRefTester.java 
import java.util.*;
import java.util.function.*;


public class MethodRefTester {
    public static void main(String...args) {
        System.out.println("constructor reference");
        BiFunction<String, Integer, Employee> hireF = Employee::new;  
        Employee mike = hireF.apply("Mike", 100000);
        System.out.println(mike.getName());
        
        System.out.println("particular object method reference");
        Supplier<String> nameF = mike::getName;  
        System.out.println(nameF.get());
        IntFunction<Integer> raiseF = mike::raise;                 
        System.out.println(raiseF.apply(10000));
        
        System.out.println("static reference");
        Supplier<String> getCompanyF = Employee::getCompany;         
        System.out.println(getCompanyF.get());
        
        System.out.println("Arbitrary object method reference");
        Comparator<Employee> isEarlierF = Employee::isEarlier;      
        Employee sam = hireF.apply("Sam", 140000);
        System.out.println(isEarlierF.compare(mike, sam));
        System.out.println(isEarlierF.compare(sam, mike));
        
        System.out.println("Functional Interface's abstract method takes 2 parameters with the same type");
        TestInterface<Employee> arbitary = Employee::isEarlier;
        System.out.println(arbitary.ok(mike, sam));
        System.out.println(arbitary.ok(sam, mike));
    }
}

@FunctionalInterface
interface TestInterface<R> {
    int ok(R a, R b);
}

class Employee {
    private String name = "";
    private static int ID = 0;
    private int id = 0;
    private static String COMPANY = "xyz.com";
    private int salary = 100000;
    
    public Employee(String name, int salary) {
        this.name = name;
        this.id = ID++;
        this.salary = salary;
    }
    //provider
    public static String getCompany() {
        return COMPANY;
    }
    
    //provider
    public String getName() {
        return this.name;
    }
    
    //function
    public int raise(int delta) {
        this.salary += delta;
        return this.salary; 
    }
    
    //Comparator
    public int isEarlier(Employee that) {
        if(this.id < that.id) {
            return 1;
        } else {
            return -1;
        }
    }
}
OCPJP>
OCPJP>javac MethodRefTester.java 
OCPJP>java MethodRefTester
constructor reference
Mike
particular object method reference
Mike
110000
static reference
xyz.com
Arbitrary object method reference
1
-1
Functional Interface's abstract method takes 2 parameters with the same type
1
-1
OCPJP>