Lambda expression allows you to reduce code compared to an 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 have reduced the number of lines of code.
For example, before Java 8, to display all elements from List
In Java 8, after using a lambda expression
Further reduction in code by let compiler infer types
and Now, since this lambda expression is not doing anything and just calling a method, it can be replaced by method reference, as shown below:
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).
For example, 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 a 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 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).
You can see also see these Java 8 Stream and Lambdas online courses to learn more about method reference and how to effectively use it to further shorten your Java code.
How to use Method reference in Java 8? Example
Here is a complete Java program that 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 a 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 is in Java 8 and how you can use it 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.
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)
Thanks for reading this article, if you like this Java 8 tutorial then please share with your friends and colleagues. If you have any suggestions 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.
What development environment do you use?
ReplyDeleteCould you pass me the color theme you use please?
Lets take a quick example :
ReplyDeleteList 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);
What is soft reference and hard reference in Java.
ReplyDeleteWhat is soft reference and hard reference in Java? If possible explain this one.
ReplyDelete