Monday, March 13, 2017

What is Method References in Java 8? An Example

Lambda expression allows you to reduce code compared to anonymous class to pass behaviors to methods, method reference goes one step further. It reduces code written in a lambda expression to make it even more readable and concise. You use lambda expressions to create anonymous methods. Sometimes, however, a lambda expression does nothing but call an existing method. In those cases, it's often clearer to refer to the existing method by name. Method references enable you to do this; they are compact, easy-to-read lambda expressions for methods that already have a name.

One of the most popular examples of method reference is List.forEach(System.out::println), which prints each element into the console. If you analyze this statement from the very beginning, you will understand how lambda expression and further method reference has reduced the number of lines of code.

Before Java 8, to display all elements from List

List listOfOrders = getOrderBook();
for(Order order : listOfOrders){
   System.out.println(order);
}


In Java 8, after using lambda expression

listOfOrders.forEach((Order o) -> System.out.println(o));

Further reduction in code by let compiler infer types

listOfOrders.forEach(System.out.println(o));


and Now, since this lambda expression is not doing anything and just a calling a method, it can be replaced by method reference, as shown below:

orderBook.forEach(System.out::println);


This is the most concise way of printing all elements of a list.  Since println() is a non-static instance method, this is known as instance method reference in Java8.

The equivalent lambda expression for the method reference String::compareToIgnoreCase would have the formal parameter list (String a, String b), where a and b are arbitrary names used to better describe this example. The method reference would invoke the method a.compareToIgnoreCase(b). If you want more examples, I suggest you reading Java SE 8 for really impatient by Cay S. Horstmann, one of the best book to learn Java 8 feature.

What is Method References in Java 8? An Example


How to use Method reference in Java 8

Here is a complete Java program which will teach you how to use method reference in your Java 8 code to further shorten your Java program:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
 
public class Test {
 
    public static void main(String args[]){
      
        // initialize order book with few orders
        List<Order> orderBook = new ArrayList<>();
        orderBook.add(new Order(1000, "GOOG.NS", 1220.17, Order.Side.BUY));
        orderBook.add(new Order(4000, "MSFT.NS", 37.47, Order.Side.SELL));
       
        // Sort all orders on price, using lambda expression
        System.out.println("Before sorting : " + orderBook);
        Collections.sort(orderBook, (a, b) -> a.getQuantity() - b.getQuantity());
               
        // replacing lambda expression to method reference
        // Above code can also be written like this, where
        // we are just calling a method of Order class from
        // lambda expression, this can be replaced by Method
        // reference.
        Collections.sort(orderBook, (a, b) -> Order.compareByQuantity(a, b));
        Collections.sort(orderBook, Order::compareByQuantity);
        System.out.println("After sorting by order quantity : " + orderBook);
   
        // Did you notice, two things while using method reference
        // first, we use :: double colon to invoke method,
        // similar to scope resolution operator of C++.
        // second, you don't need to provide parenthesis
        // for method parameter, it’s just a name
        // Similarly you can call other static method 
        // using method reference.
        // Another key thing is syntax of method must
        // match with syntax of functional
        // interface, for example compareByQuantity() syntax
        // is same as compare() method of
        // Comparator interface, which is a functional
        // interface and Collections.sort() accept
        // Comparator. Let's sort this List by trade value
        Collections.sort(orderBook, Order::compareByValue);
        System.out.println("After sorting by trade value : " + orderBook);
      
        // Java supports four types of method reference,
        // let's see example of each of them
        // Our previous example, in which we are
        // referring to static method was an
        // example of static method reference,
        // while below is an example of instance method
        // reference, where we are invoking and instance
        // method from Order class.
        // You can reference a constructor in the same way
        // as a static method by using the name new
       
        Order order = orderBook.get(0); // you need a reference of object
        Collections.sort(orderBook, order::compareByPrice);
        System.out.println("Order book after sorting by price : " + orderBook);
       
        // method reference example of an Arbitrary Object of a Particular Type
        // equivalent lambda expression for following would be
        // (String a, String b)-> a.compareToIgnoreCase(b)
        String[] symbols = { "GOOG.NS", "APPL.NS", "MSFT.NS", "AMZN.NS"};
        Arrays.sort(symbols, String::compareToIgnoreCase);
       
    }
}
 
 
class Order {
    public enum Side{
        BUY, SELL
   };
    private final int quantity;
    private final String symbol;
    private final double price;
    private final Side side;
 
    public Order(int quantity, String symbol, double price, Side side) {
        this.quantity = quantity;
        this.symbol = symbol;
        this.side = side;
        this.price = price;
    }
 
    public int getQuantity() { return quantity; }
    public String getSymbol() { return symbol; }
    public double getPrice() { return price; }
    public Side getSide() { return side; }
 
    @Override
    public String toString() {
        return String.format("%s %d %s at price %.02f",side, quantity, symbol, price);
    }
   
    public static int compareByQuantity(Order a, Order b){
        return a.quantity - b.quantity;
    }
   
    public int compareByPrice(Order a, Order b){
        return Double.valueOf(a.getPrice()).compareTo(Double.valueOf(b.getPrice()));
    }
   
    public static int compareByValue(Order a, Order b){
        Double tradeValueOfA = a.getPrice() * a.getQuantity();
        Double tradeValueOfB = b.getPrice() * b.getQuantity();
        return tradeValueOfA.compareTo(tradeValueOfB);
    }
   
}
 
Output:
Before sorting : [BUY 1000 GOOG.NS at price 1220.17, SELL 4000 MSFT.NS at price 37.47]
After sorting by order quantity : [BUY 1000 GOOG.NS at price 1220.17, SELL 4000 MSFT.NS at price 37.47]
After sorting by trade value : [SELL 4000 MSFT.NS at price 37.47, BUY 1000 GOOG.NS at price 1220.17]
Order book after sorting by price : [SELL 4000 MSFT.NS at price 37.47, BUY 1000 GOOG.NS at price 1220.17]



Points to remember about Method Reference in Java 8

1) There are four types of method reference in Java 8, namely reference to static method, reference to an instance method of a particular object, reference to a constructor and reference to an instance method of an arbitrary object of a particular type. In our example, the method reference Order::compareByQuantity is a reference to a static method.

2) The double colon operator (::) is used for the method or constructor reference in Java. This same symbol is used scope resolution operator in C++ but that has nothing to do with method reference.


That's all about what is method reference in Java 8 and how you can use to write clean code in Java 8. The biggest benefit of the method reference or constructor reference is that they make the code even shorter by eliminating lambda expression, which makes the code more readable. You can see Java SE 8 for really impatient to learn more about method reference and how to effectively use to further shorten your Java code.

Other Java 8 Tutorials you may like to explore
  • 20 Examples of Date and Time API in Java 8 (tutorial)
  • How to use Integer.compare() in Java 8 to compare String by length? (tutorial)
  • How to parse String to LocalDateTime in Java 8? (tutorial)
  • How to use Map Reduce in Java 8? (tutorial)
  • How to convert java.util.Date to java.time.LocalDateTime in Java 8? (tutorial)
  • How to convert String to LocalDateTime in Java 8? (tutorial)
  • How to get current day, month and year in Java 8? (tutorial)
  • How to calculate the difference between two dates in Java? (example)
  • How to use flatMap() function in Java 8? (example)
  • How to join multiple String by a comma in Java 8? (tutorial)
  • How to use peek() method in Java 8? (tutorial)
  • 5 books to learn Java 8 and Functional Programming (books)

Further Learning
What's New in Java 8
From Collections to Streams in Java 8 Using Lambda Expressions

Thanks for reading this article, if you like this Java 8 tutorial then please share with your friends and colleagues. If you have any suggestion to improve this article or any feedback then please drop a note. If you have a question then feel free to ask, I'll try to answer it.

4 comments :

Bryan Cortés Fernández said...

What development environment do you use?

Could you pass me the color theme you use please?

SARAL SAXENA said...

Lets take a quick example :

List numbers=Arrays.asList(1,2,3,4,5);
Now we can print this numbers using java 8 forEach.

numbers.forEach(number->System.out.println(number));
So like in the above example lambda expression does nothing it just simply pass through the number into sysout method. and we are very much clear we are printing a list of integer. so in this case we can use method reference .method references are easy , compact, easy-to-read lambda expressions for methods that already have a name.

numbers.forEach(System.out::println);

Anonymous said...

What is soft reference and hard reference in Java.

Deepa said...

What is soft reference and hard reference in Java? If possible explain this one.

Post a Comment