Item 43: Prefer method references to lambdas

Introduction

Method references are more concise than lambdas. If method references are shorter and clearer, use them; otherwise, utilize lambdas. Method references reduce the boilerplate code and thus improves readability.

There are four kinds of method references, which are summarized below:

KindExample
Reference to a static methodContainingClass::staticMethodName
Reference to an instance method of a particular objectcontainingObject::instanceMethodName
Reference to an instance method of an arbitrary object of a particular typeContainingType::methodName
Reference to a constructorClassName::new
Static Method Reference

Suppose that you have a list of numbers and want return integers using Integer.parseInt()

List<String> numbers = Arrays.asList("1", "2", "3");

You can accomplish this by using lambda expression as follows

// lambda equivalent
numbers.forEach(name -> Integer.parseInt(name));
System.out.println("lambda equivalent: " + numbers);

Or, you can use the method reference. Integer::parseInt is a reference to a static method.

// method reference
numbers.forEach(Integer::parseInt);
System.out.println("method reference: " + numbers);
Reference to an instance method of a particular object

Suppose that the members of your workout application are contained in an array, and you want to sort the array by duration. You could use the following code.

class WorkoutComparator implements Comparator<Workout> {
	@Override
	public int compare(Workout a, Workout b) {
		return a.getDuration().compareTo(b.getDuration());
	}
}

The following is an example of a reference to an instance method of a particular object.

Workout[] workoutArray = 
{ 
     new Workout(60, "chest&back"), 
     new Workout(50, "biceps&triceps"), 
     new Workout(70, "shoulders&legs")
};

WorkoutComparator myWorkoutComparator = new WorkoutComparator();

The method reference myWorkoutComparator::compare invokes the method compare that is part of the object myWorkoutComparator. The JRE infers the method type arguments, which in this case are (Workout, Workout)

Arrays.sort(workoutArray, myWorkoutComparator::compare);
Reference to an instance method of an arbitrary object of a particular type

The following is an example of a reference to an instance method of an arbitrary object of a particular type

String[] family = { "Suleyman", "Canan", "Fatma", "Omur", "Tomis" };

// method reference
Arrays.sort(family, String::compareTo);

// The equivalent lambda expression for the method reference
Arrays.sort(family, (a, b) -> a.compareTo(b)); 
Reference to a Constructor

Constructor references are similar to the method references. We just need to use the new operator. For instance, Workout::new is a reference to a Workout constructor.

Let’s create a list of Workout types.

List<String> workputTypes = Arrays.asList("chest", "back", "legs");

map() converts the stream of workout types to stream of Workout objects. Note that Workout::new equals to new Workout(“workout type”), such as new Workout(“chest“). The toArray accepts a constructor reference and creates an array of workout objects.

Workout[] workouts = workputTypes.stream()
			.map(Workout::new)
			.toArray(Workout[]::new);
		
for (Workout workout : workouts)
   System.out.println(workout.getType() + " : "+ workout.getDuration());
Conclusion

In this item, we introduced four kinds of method references. If method references are shorter and clearer, use them; otherwise, utilize lambdas. The code is available on GitHub.

Leave a Reply

Your email address will not be published. Required fields are marked *