lambda Expression in Java :

Reading Time: 6 minutes

What are lambda expressions in Java?

Lambda idioms are an unknown function, meaning they have no name or identifier. we can transfer it as a parameter to another function and they are paired with an active visual connector and insert a parameter with a sentence referring to that parameter.

The syntax of a basic lambda expression is:

parameters -> expression

we can used it as the coded version of the invisible path (named but empty method) within a paired visual interface.

Unlike most works in Java, lambda expressions exist without the scope of anything, So this means that they crash anywhere in the system and we can transferred it. In simple terms, lambda expressions allow tasks to behave like another piece of data.

Lambda use cases in Java

Lambda speakers are used to accomplish an unknown phase function, without the use of clutter they are ready to repeat the simple treatment that can be used in multiple locations throughout the system, for example, to add two values ​​without changing the input data.

These structures make the lambda especially useful editing styles that work in Java. Prior to Java 8, Java struggled to find tools to meet all of the requirements of active programming

Functional programming has 5 key principles:

Pure Functions: Occupations that sort out autonomously from the public authority of work and that just hold back fundamental tasks to get the result.

Immutability: Input indicated, unaltered. Errands ought to keep away from complex restrictive ways of behaving. all tasks should return similar worth regardless of how frequently it is called.

First Class Functions : Undertakings are treated similarly as some other worth.you can fill similar individuals with undertakings, relegate errands like boundaries, and so forth.

High-order functions: Works with high order or one or more functions such as parameters or return functionality. This is important in creating complex behaviors with a functional system.

Function Composition: Numerous straightforward undertakings can be gathered into various orders to make complex errands. Straightforward errands complete a solitary advance that can be allocated to numerous assignments, while complex undertakings complete the whole assignment.

Lambda Speeches help us achieve clean jobs, consistency, and first-class operating principles in Java.

Lambda works are unadulterated on the grounds that they don’t rely upon the expansiveness of a specific class. They don’t change since they allude to the sent boundary yet don’t change the worth of the boundary to accomplish

How to write :

Lambda functions can have any number of arguments but only one expression. The expression is evaluated and returned and We can use lambda functions wherever function objects are required.

parameter -> expression

A single lambda expression can also have multiple parameters:

(parameter1, parameter2) -> expression

The speech part, or body of a lambda, contains a parameter reference. Lambda expression value is the expression value when used with the transmitted parameters.

For example:

import java.util.ArrayList;
 
public class main {
  public static void main(String[] args) {
    ArrayList<Integer> numbers = new ArrayList<Integer>();
    numbers.add(1);
    numbers.add(2);
    numbers.add(3);
    numbers.add(4);
    numbers.forEach( (n) -> { System.out.println(n); } );
  }
}

The parameter n is passed to the expression System.out.println(n). The expression then executes using the value of the parameter n in the print statement. This repeats for each number in the ArrayList, passing each element in the list into the lambda expression as n. The output of this expression is therefore a printed list of the ArrayList’s elements: 1 2 3 4.

Lambda Function Body

The lambda function body can contain expressions over multiple lines if encased in curly braces.

For example:

(Mname,Fname) -> {
    System.out.println("Mother Name is : " + Mname);
    System.out.println("Father Name is : " + Fname);
  }

This allows for more complex expressions that execute code blocks rather than a single statement.

You can also return from lambda functions by adding a return statement within the function body.

 public static Addition getAddition() {
      return (a, b) -> a + b; // lambda expression return statement
   }

Lambda even has its own return statement:

(a, b) -> a + b;

The compiler assumes that a+b is our return value. This syntax is cleaner and will produce the same output as the previous example.

Regardless of how long or complex the expression gets, remember that lambda expressions must immediately output a consistent value. This means an expression cannot contain any conditional statements like if or while and cannot wait for user input.

Lambdas as Objects

You can send lambdas to other functions as parameters. Imagine that we want to create a greeting program that is open for more greeting functions to be added in different languages.

public class WellWisher {
    public static void wish(Greeting greeting) {
        greeting.greet();
    }
    // Passing a lambda expression to the wish method
    public static void main(String args[]) {
        wish( () -> System.out.println("Good Morning !!!") );
    }
}
@FunctionalInterface
public interface Greeting {
    void greet();
}

Here the expression itself is passed, and the greet(); function is immediately executed. From here, we can add additional greet functions for different languages that will override to print only the correct greeting.

Interfaces in Java

Interfaces in Java are similar to classes. They are blueprints that contain variables and methods. However, interfaces contain only abstract methods that have signatures but no code implementation.

The interface says what features it must have but not how to implement them.

For example, you might have an interface Character that lists methods for all the things a character in a video game must be able to do. The interface lists that all characters must have a move() method but leaves it up to the class of the individual characters to define the distance and means (flight, running, sliding, etc.) of movement.

The syntax of an interface is:

interface <interface_name> {
    
    // declare constant fields
    // declare methods that abstract 
    // by default.
}

With the help of interfaces, Java classes can achieve multiple inheritance.It also helps us achieve total abstraction since the interface holds no scope or values by default.

We can use lambda expressions for expressing the instances of interfaces. Before Java 8, we had to create an inner anonymous class to use these interfaces.

Before JSE8:


// functional interface before java8
  
class Test 
{ 
    public static void main(String args[]) 
    { 
        // create anonymous inner class object 
        new Thread(new Runnable() 
        { 
            @Override
            public void run() // anonymous class
            { 
                System.out.println("here new thread is created"); 
            } 
        }).start(); 
    } 
} 

After JSE8:

// functional interface using lambda expressions 
  
class Test 
{ 
  public static void main(String args[]) 
  { 
  
    // lambda expression to create the object 
    new Thread(()-> 
       {System.out.println("here new thread is created");}).start(); 
  } 
} 

Functional Interfaces

Lambda articulations can utilize dynamic correspondence, which is correspondence with only one undetectable way. The lambda articulation essentially gives the body in an imperceptible manner inside the noticeable working connector.

If the visual connector had more than one ambiguous method, the producer would not have known which method he should use the lambda expression as its body. Typical examples of built-in Comparator or Predicate workspaces.

It is best practice to add an optional @ FunctionalInterface annotation to the top of any active visual interface.

Java recognizes the annotation as a limitation that the marked visual interface can have only one invisible path. If there is more than one way, the moderator will send an error message.

Using an annotation ensures that no unexpected behavior arises from the lambda expression that calls for this interface.

@FunctionalInterface
interface cube 
{ 
    int calculate(int x); 
}

Default methods in interfaces

Effective communication is limited to invisible routes. Also there is no limit to default or vertical routes. Automatic or static methods can adjust our communication to share different behaviours with asset classes.

Programmed techniques can include a body inside the noticeable connector. Above all, computerized strategies for visual connectors give extra usefulness in a specific kind without isolating use classes.

To fix it, we should furnish people with the utilization of that strategy at all phases of execution.

However, sometimes the methods have only one implementation, and there is no need to provide their functionality for each class. If so, we can refer to that method as the default in the interface and assign its implementation to the interface itself.

public interface Vehicle {
    void cleanVehicle();
    default void checkVehicle() {
        System.out.println("here Vehicle is being checked....!!");
    }
}

Here, the default method is checkVehicle() while cleanVehicle() is abstract. Regardless of the implementing class, checkVehicle() will always print the same phrase. Since the behavior does not change based on the class, we can simply use the default method to avoid repeated code.

Most importantly, the Vehicle interface still only has 1 abstract method and therefore is counted as a functional interface that can be used with lambda expressions.

Static methods in interfaces

The static strategies in connection points are like default techniques and we can not abrogate these techniques. Static techniques are extraordinary when you need a strategy’s execution to be unchangeable by carrying out classes.

Car.Java class :

public abstract class Car implements Vehicle {
    public static void repair(Vehicle vehicle){
        vehicle.repairVehicle();
    }
    public static void main(String args[]){
        
        Vehicle.cleanVehicle(); //This will compile.
        Car.repair(() -> System.out.println("Car repaired"));
    }
}

Vehicle.Java class :

//functional interface
public interface Vehicle {
    static void cleanVehicle(){
        System.out.println(" vehicle is being cleaned..!!");
    }
    void repairVehicle();
}

In the Car class, we’re able to call cleanVehicle() to produce the implementation defined in our interface. If we attempt to @Override the cleanVehicle() method, we’ll get an error message because it was declared static.

Finally, we can still use this interface in our lambda expressions because repairVehicle() is our only abstract method.

Written by 

Udit is a Software Consultant at Knoldus . He has completed his Masters of Computer Applications from Vellore institute of Technology. He is enthusiastic ,hard-working and determine person with strong attention to detail and eager to learn about new technologies.

Discover more from Knoldus Blogs

Subscribe now to keep reading and get access to the full archive.

Continue reading