As we already aware of using lambdas which make code shorter.Method reference is another way to make code shorter and easier to read. It is compact and easy form of lambda expression
If your lambda expression is like this:
str -> System.out.println(str)
then you can replace it with a method reference like this:
System.out::println
The :: operator is used in method reference to separate the class or object from the method name
Four types of method references
- Calling Static method of a class – Class::staticMethod
- Calling Instance method of a Particular object – object::instanceMethod
- Calling Instance method on a Parameter – Class::instanceMethod
- Calling Constructor
1. Calling Static method of a class
We’ll begin with a very simple example, capitalizing and printing a list of Strings:
List<String> messages = Arrays.asList("hello", "test", "demo");
simple lambda expression calling the StringUtils.capitalize() method directly:
messages.forEach(word -> StringUtils.capitalize(word));
Or, we can use a method reference to simply refer to the capitalize static method:
1 |
messages.forEach(StringUtils::capitalize); |
2. Calling Instance method of a Particular object
To demonstrate this type of method reference, let’s consider two classes:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class Bicycle { private String brand; private Integer frameSize; // standard constructor, getters and setters } public class BicycleComparator implements Comparator { @Override public int compare(Bicycle a, Bicycle b) { return a.getFrameSize().compareTo(b.getFrameSize()); } } |
And, let’s create a BicycleComparator object to compare bicycle frame sizes:
1 |
BicycleComparator bikeFrameSizeComparator = new BicycleComparator(); |
We could use a lambda expression to sort bicycles by frame size, but we’d need to specify two bikes for comparison:
1 2 |
createBicyclesList().stream() .sorted((a, b) -> bikeFrameSizeComparator.compare(a, b)); |
Instead, we can use a method reference to have the compiler handle parameter passing for us:
1 2 |
createBicyclesList().stream() .sorted(bikeFrameSizeComparator::compare); |
3. Calling Instance method on a Parameter
This type of method reference is similar to the previous example, but without having to create a custom object to perform the comparison.
Let’s create an Integer list that we want to sort:
1 |
List<Integer> numbers = Arrays.asList(5, 3, 50, 24, 40, 2, 9, 18); |
If we use a classic lambda expression, both parameters need to be explicitly passed, while using a method reference is much more straightforward:
1 2 3 4 |
numbers.stream() .sorted((a, b) -> a.compareTo(b)); numbers.stream() .sorted(Integer::compareTo); |
4. Calling Constructor
We can reference a constructor in the same way that we referenced a static method in our first example. The only difference is that we’ll use the new keyword.
Let’s create a Bicycle array out of a String list with different brands:
1 |
List<String> bikeBrands = Arrays.asList("Giant", "Scott", "Trek", "GT"); |
First, we’ll add a new constructor to our Bicycle class:
1 2 3 4 |
public Bicycle(String brand) { this.brand = brand; this.frameSize = 0; } |
Next, we’ll use our new constructor from a method reference and make a Bicycle array from the original String list:
1 2 3 |
bikeBrands.stream() .map(Bicycle::new) .toArray(Bicycle[]::new); |
Notice how we called both Bicycle and Array constructors using a method reference, giving our code a much more concise and clear appearance.
Leave a Reply