Tuesday, October 30, 2018

How to Convert a Lambda Expression to Method Reference in Java 8?

If you have been coding in Java 8 then you may know that using method reference in place of lambda expression makes your code more readable, hence it is advised to replace lambda expression with method reference wherever possible. But, the big question is, how do you find whether you can replace a lambda with method reference? Yes, it's not that easy, especially if you have been using Java 8 only for a couple of months and struggling to get the functional programming concepts and idioms sorted in your head. Sometimes, IDEs like IntelliJ IDEA and Eclipse does offer some hints to convert lambda expression to method reference but it does make sense to learn the logic behind it, otherwise, it won't make sense.


The simple rule to replace lambda expression with method reference is built on common sense, which you will learn in this article.

If you look closely, lambda is nothing but a code block which you pass to a function to execute. If you already have that code in form of a method then instead of passing the new code as lambda you can pass the name of the method and that's known as method reference.

That's it, but I know, it's easier said than done, hence I have provided a couple of examples to explain method reference concept in Java 8.

Btw, if you are just starting with lambda expression and Java 8 in general, I suggest you to first go through a comprehensive course like The Complete Java MasterClass, which covers the topic in much more detail. It's also one of the best course to learn Java in general and also recently updated to cover the Java 11 features.




How to replace lambda expression with method reference in Java 8

If you are using a lambda expression as an anonymous function but not doing anything with the argument passed, you can replace lambda expression with method reference.

Below code is a good example to replace lambdas with method reference


listOfNumbers.stream().sorted().forEach(number -> {
  System.out.println(number);
  }
);

Since we are not modifying the number argument here, we can replace the lambda expression:

number -> { 
  System.out.println(number); 
} 

with method reference as shown below:

listOfNumbers.stream().sorted.forEach(System.out::println);

but, if you modify the argument before passing it to another method then you cannot replace lambdas with method reference e.g. in the following case we cannot do that:

listOfNumbers.stream().sorted().forEach(number -> {
  System.out.println(String.valueOf(number));
  }
);


The double colon (::) operator is used for method reference and there are actually three main cases to use it:

object::instanceMethod
Class::staticMethod
Class:instanceMethod

In the first two cases, the method reference is equivalent to lambda expression that supplies the parameters of the method e.g. System.out::println is equivalent to x -> System.out.println(x) and Math::pow is equivalent to (x, y) -> Math.pow(x, y).

In this case, the first parameter becomes the target of the method.

For example, String::compareToIgnoreCase is the same as

(x, y) -> x.compareToIgnoreCase(y) 

or

this::equals is the same as

(x -> this.equals(x))

You can read more about converting this type of lambda expression into method reference in What's New in Java 8, it has got a little bit more explanation and examples on this topic.

How to convert a lambda expression to method reference in Java 8?



Btw, you would need a Pluralsight membership to access this course, which costs around $29 monthly or $299 annually (14% saving). I have one and I also suggest all developers have that plan because Pluralsight is like NetFlix for Software developers.

It has more than 5000+ good quality courses on all latest topics. Since we programmers have to learn new things every day, an investment of $299 USD is not bad.

Btw, it also offers a 10-day free trial without any obligation which allows you to watch 200 hours of content. You can watch this course for free by signing for that 10-day free trial.


Anyway,  another good example of replacing lambda expression with method reference is the following code of sorting a map by values in Java 8:

Map sortByValue = map.entrySet()
.stream()
.sorted(Map.Entry.<String, Integer>comparingByValue())
.collect(Collectors.toMap(e -> e.getKey(),e -> e.getValue()));


can be rewritten as following using method reference :

Map sortByValue = map.entrySet()
.stream()
.sorted(Map.Entry.<String, Integer>comparingByValue())
.collect(toMap(Map.Entry::getKey,
               Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));


if you look closely, we have replaced e -> e.getKey() with Map.Entry::getKey and e -> g.getValue() to Map.Entry::getValue because we already have code what those lambda expressions were doing in form of getKey() and getValue() method.

That's all about when and how to replace lambda expression with method reference in Java 8. You can replace only if you are not doing any modification, otherwise, you cannot replace. Why you want to do that? Well, because method reference is more succinct and readable than lambda expression.


Further Learning
What's New in Java 8
The Complete Java MasterClass - Updated for Java 11
Java SE 8 for Really Impatient
Refactoring to Java 8 Streams and Lambdas Self- Study Workshop


Related Java 8 Tutorials
If you are interested in learning more about new features of Java 8, here are my earlier articles covering some of the important concepts of Java 8:
  • 20 Examples of Date and Time in Java 8 (tutorial)
  • 5 Books to Learn Java 8 from Scratch (books)
  • How to join String in Java 8 (example)
  • How to use filter() method in Java 8 (tutorial)
  • How to format/parse the date with LocalDateTime in Java 8? (tutorial)
  • How to use Stream class in Java 8 (tutorial)
  • How to use forEach() method in Java 8 (example)
  • How to convert List to Map in Java 8 (solution)
  • How to use peek() method in Java 8 (example)
  • How to sort the map by keys in Java 8? (example)
  • 10 examples of Optionals in Java 8? (example)
  • Top 5 Java 8 Courses for Programmers (courses)
Thanks for reading this article so far. If you like this article then please share with your friends and colleagues. If you have any question or feedback then please drop a comment.

P. S. - If you don't mind learning from free resources then you can also check out this list of free Java 8 and Java 9 courses to learn better. 

1 comment :

Tomtom said...

Hi,
SonarLint helps finding where a lambda expression can be replaced by method reference.

Post a Comment