DEV Community

Rishikrishna
Rishikrishna

Posted on

Lambda Expressions in Java

In Java, we all know we can pass data as arguments, but what about passing functionality as an argument? In this tutorial, we'll see just how to do that. Let me explain that with an ideal use case.

Ideal use case

Suppose you are building a car tracking application for the country, and you want to display all cars of a particular state.For example Tamil Nadu, the vehicle number of a car contains 'TN' in it.

One would represent a Car like this:

public class Car {
  String modelName;
  int modelNum;
  LocalDate registrationDate;
  String vehicleNum;             

  public String getModelName(){..}

  public void printCar() {..}

  ...
}
Enter fullscreen mode Exit fullscreen mode

Approach 1: Create methods for the search criteria.

public static void printCarsIn(List<Car> cars, String state){
 for(Car c : cars) {
  if(c.getVehicleNum().contains(state)){
    c.printCar();
  }
 }
}

printCarsIn(cars, "TN");
Enter fullscreen mode Exit fullscreen mode

You are checking each instance of the cars list to see if it's vehicle number contains 'TN' in it. If so, you print it.

This approach is more likely to make your application brittle. What if you update Car class so that it contains different members or perhaps different data types for its members. Or what if the search criteria is changed. You have to rewrite a lot of code in all of the defined methods. The search criteria can instead be separated into a different class.

Approach 2: Specify search criteria in a local class.
The following class checks whether an instance of Car is from Tamil Nadu.

interface CheckCar {
  boolean test(Car c, String state);
}

class CheckCarsInState implements CheckCar {
  public boolean test(Car c, String state) {
    return c.getVehicleNum().contains(state);
  }
}
Enter fullscreen mode Exit fullscreen mode

Now, you can create an instance of this CheckCarsInState class and use it to check the criteria.

public static void printCarsIn(List<Cars> cars, String state, CheckCar tester){
  for(Car c : cars){
    if(tester.test(c, state)){
      c.printCar();
    }
  }
}

printCarsIn(cars, "TN", new CheckCarsInState());
Enter fullscreen mode Exit fullscreen mode

Although we have separated the search criteria, we have additional code for declaring a new class.

Approach 3: Using an anonymous class

An anonymous class can be used if only one instance is required from a class.

interface CheckCar {
  boolean test(Car c, String state);
}

public static void printCarsIn(List<Cars> cars, String state, CheckCar tester){
  for(Car c : cars){
    if(tester.test(c, state)){
      c.printCar();
    }
  }
}

//method call
printCarsIn(cars, "TN", new CheckCar() {
  public boolean test(Car c, String state) {
    return c.getVehicleNum().contains(state);
  }
});
Enter fullscreen mode Exit fullscreen mode

But still, the anonymous class looks bulky considering the CheckPerson interface contains only one method. We can instead use a lambda expression.

Approach 4: Lambda expression to pass functionality
The CheckPerson is a functional interface (an interface with only one abstract method). Lambda expressions can be used against functional interfaces.

interface CheckCar {
  boolean test(Car c, String state);
}

public static void printCarsIn(List<Cars> cars, String state, CheckCar tester){
  for(Car c : cars){
    if(tester.test(c, state)){
      c.printCar();
    }
  }
}

printCarsIn(cars, "TN", (c, state) -> c.getVehicleNum().contains(state));
Enter fullscreen mode Exit fullscreen mode

With lambda expressions, you specify the criteria for which you want to search when calling the function.

Syntax of Lambda expression

  • Parameter list: A list of parameters enclosed in parentheses. The parentheses can be avoided if only one parameter is used.
c -> c.printCar();
Enter fullscreen mode Exit fullscreen mode
  • Arrow token, ->

  • Body: The body can either be a block of statements or an expression. If it is a single expression, the evaluation will be returned. Alternatively, you can use a return statement like so,

c -> {
  //...
  return c.getVehicleNum();
}
Enter fullscreen mode Exit fullscreen mode

Note: A single return statement is not an expression, so it can't be used without braces.

Thanks for reading the blog. Feel free to provide inputs and suggestions for any areas of improvement. :)

Top comments (1)

Collapse
 
pragmacoder profile image
Pragma coder

Noice and clear!