Java 8 - Method references introduction with examples

Posted on April 8, 2017


Before we start, it is recommended that you read the following articles on lambda expression.

Method reference is related to lambda expression which refers to a constructor or method by their names.  Sometimes, a lambda expression does nothing but call an existing method as follows.

Predicate predicate1 = (n) -> EvenOddCheck.isEven(n);

Using method references, we can write the above lambda expression as follows.

Predicate predicate2 = EvenOddCheck::isEven;

It is clear from the above statement that method references enable us to write a lambda expression in more compact and readable form.  Double colon :: operator is used for method references.

Note:- The target type for a method reference and lambda expression must be a functional interface (abstract single method interface).  

Here is the complete example of how to use the method references in java program.

package com.boraji.tutorial;

/*
 * Functional Interface
 */
interface Predicate {
   boolean test(int n);
}

class EvenOddCheck {
   public static boolean isEven(int n) {
      return n % 2 == 0;
   }
}

public class MethodReferenceExample1 {

   public static void main(String[] args) {
      // Using lambda expression
      Predicate predicate1 = (n) -> EvenOddCheck.isEven(n);
      System.out.println(predicate1.test(20));

      // Using method reference
      Predicate predicate2 = EvenOddCheck::isEven;
      System.out.println(predicate2.test(25));
   }
}

There are four types of method references.

TypeExample
Reference to a static methodMath::random;
Reference to an instance method of a particular object(new Random())::nextInt;
Reference to an instance method of an arbitrary object of a particular typeString::toUpperCase;
Reference to a constructorString:: new;

Reference to a static method

The following example prints the even numbers of a stream using lambda expression and method reference to static method.

MethodReferenceExample1.java

package com.boraji.tutorial;

import java.util.Arrays;
import java.util.List;

/**
 * @author imssbora
 */
class EvenOddChecker {
   public static boolean isEven(int n) {
      return n % 2 == 0;
   }
}

public class MethodReferenceExample1 {

   public static void main(String[] args) {
      List<Integer> numbers = Arrays.asList(20, 10, 15, 24, 55, 47, 16, 87, 88);

      // Print even numbers using lambda expression
      numbers.stream().map((n) -> EvenOddCheck.isEven(n))
          .forEach((n) -> System.out.println(n));
      
      // Print even numbers using method references
      numbers.stream().map(EvenOddCheck::isEven)
         .forEach(System.out::println);
   }

}

Output

--------Even numbers----------
20
10
24
16
88
--------Even numbers----------
20
10
24
16
88

Reference to an instance method of a particular object

Here is an example of using method reference to an instance method of a particular object.

MethodReferenceExample2.java

package com.boraji.tutorial;

import java.util.function.BiFunction;

/**
 * @author imssbora
 */
class MathOperation {
   // Addition
   public int add(int a, int b) {
      return a + b;
   }
   // Subtraction
   public int sub(int a, int b) {
      return a + b;
   }
}

public class MethodReferenceExample2 {

   public static void main(String[] args) {

      MathOperation op = new MathOperation();

      System.out.println("--------------------Using lambda expression----------------------");
      BiFunction<Integer, Integer, Integer> add1 = (a, b) -> op.add(a, b);
      System.out.println("Addtion = " + add1.apply(4, 5));

      BiFunction<Integer, Integer, Integer> sub1 = (a, b) -> op.sub(a, b);
      System.out.println("Subtraction = " + sub1.apply(58, 5));

      System.out.println("---------------------Using method reference---------------------");
      BiFunction<Integer, Integer, Integer> add2 = op::add;
      System.out.println("Addtion = " + add2.apply(4, 5));

      BiFunction<Integer, Integer, Integer> sub2 = op::sub;
      System.out.println("Subtraction = " + sub2.apply(58, 5));
   }
}

Output

--------------------Using lambda expression----------------------
Addtion = 9
Subtraction = 63
---------------------Using method reference---------------------
Addtion = 9
Subtraction = 63

 

Reference to an instance method of an arbitrary object of a particular type

Here is an example of using method Reference to an instance method of an arbitrary object of a particular type.

MethodReferenceExample3.java

package com.boraji.tutorial;

import java.util.ArrayList;
import java.util.List;

/**
 * @author imssbora
 */
public class MethodReferenceExample3 {

   public static void main(String[] args) {
      List<String> weeks = new ArrayList<>();
      weeks.add("Monday");
      weeks.add("Tuesday");
      weeks.add("Wednesday");
      weeks.add("Thursday");
      weeks.add("Friday");
      weeks.add("Saturday");
      weeks.add("Sunday");
      
      System.out.println("--------------Using lambda expression-----------------");
      weeks.stream().map((s)-> s.toUpperCase())
         .forEach((s)->System.out.println(s));
      
      System.out.println("--------------Using method reference-----------------");
      weeks.stream().map(String::toUpperCase)
      .forEach(System.out::println);
   }
}

Output

--------------Using lambda expression-----------------
MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
SUNDAY
--------------Using method reference-----------------
MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
SUNDAY

Reference to a constructor

Here is an example of using method reference to a constructor.

MethodReferenceExample4.java

package com.boraji.tutorial;

import java.util.function.BiConsumer;

/**
 * @author imssbora
 */
class MathOperations {
   public MathOperations(int a, int b) {
      System.out.println("Sum of " + a + " and " + b + " is " + (a + b));
   }
}

public class MethodReferenceExample4 {

   public static void main(String[] args) {

      System.out.println("------------Using lambda expression------------");
      BiConsumer<Integer, Integer> addtion1 = (a, b) -> new MathOperations(a, b);
      addtion1.accept(10, 20);
      
      System.out.println("\n------------Using method reference------------");
      BiConsumer<Integer, Integer> addtion2 = MathOperations::new;
      addtion2.accept(50, 20);
   }
}

Output

------------Using lambda expression------------
Sum of 10 and 20 is 30

------------Using method reference------------
Sum of 50 and 20 is 70