Saturday, August 12, 2017

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

If you have been coding in Java 8 then you 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. Anyway, 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 which you pass to a function to execute. If you already have that code in form of a method then instead of passing new code as lambda you can pass method reference. That's it, but I know, it's easier said than done, hence I have provided a lot of examples to explain this concept in Java 8.


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 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 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 same as

(x -> this.equals(x))

You can read more about converting this type of lambda expression into method reference in Java SE 8 for Really Impatient, it has got little bit more explanation and examples on this topic.




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 Reading
What's New in Java 8
Java SE 8 for Really Impatient
From Collections to Streams in Java 8 Using Lambda Expressions
Streams, Collectors, and Optionals for Data Processing in Java 8



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)

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.

No comments :

Post a Comment