Friday, February 1, 2019

Lamda Expressions Concepts


Lambda expression leverages functional programming in Java. Lambda expression contains the implementation of a single function within the instance of an interface. The close similarity of lambda expression is anonymous inner class implementation of an interface.

Lambda expressions implement functional interfaces. A functional interface is an interface that can contain only one abstract method. A functional interface can however contain several default methods and static methods.

Let's define one functional interface like the following:
  @FunctionalInterface
  public interface Greeting {
    public void sayGreeting(String message);
  }

Here use of annotation @FunctionalInterface is recommended since it enforces to use only one abstract method. Lets first implement it with anonymous inner class:
    Greeting greetingImpl = new Greeting() {
          @Override
          public void sayGreeting(String message) {
                System.out.println(message);
          }
    };
    greetingImpl.sayGreeting("Hello from Anonymous inner class.");

Using lambda expression for doing the same task will make the code shorter and cleaner.
    Greeting greetingLambda = message -> System.out.println(message);
    greetingLambda.sayGreeting("Hello from Lambda expression");
Lambda expression syntax:
(argument-list) -> {body}
Java lambda expression is consisted of three parts:
  • Argument-list: It can be empty or non-empty.
  • Arrow-token: It is used to link arguments-list and body of expression.
  • Body: It contains expressions and statements for lambda expression.
Type declaration can be included
MathOperation addition = (int a, int b) -> a + b;
Type declaration can be omitted
MathOperation subtraction = (a, b) -> a - b;
Lambda expression can contain return statement along with curly braces
    MathOperation multiplication = (int a, int b) -> {
          return a * b;
    };
Lambda as method argument:
We can pass both lambda expression as method arguments. For example, let’s consider a method:
  public static void callWithLambda(Greeting greeting, String message) {
    greeting.sayGreeting(message);
  }

We can call the above method like the following:
    callWithLambda(message -> System.out.println(message), 
          "Lambda argument pass test1");

Generic Functional Interfaces
Functional interfaces can be generic.
@FunctionalInterface
interface GenericInterface {
  void test(T param);
}
Lambda expression can associate with generic functional interfaces.
    GenericInterface genericInterface1 = (str) -> System.out.println(str);
    genericInterface1.test("Test generic interface with type string");
    
    GenericInterface genericInterface2 = (i) -> System.out.println(i);
    genericInterface2.test(5);
Method Reference:
There is a shortcut of using lambda expression. That is called method reference. It will make code even shorter. Double colon (::) is used as the syntax of method reference.
Greeting greetingLambda = message -> System.out.println(message);
Equivalent use of method reference
    Greeting greetingMethodReference = System.out::println;
    greetingMethodReference.sayGreeting("Hello from method reference");
Can be used as method argument also:
callWithLambda(System.out::println, "Lambda argument pass test2");
We can reference the following types of methods:
  • Static method:
    public static void defaultGeeting(String message) {
        System.out.println(message);
      }
    callWithLambda(LambdaTest::defaultGeeting, "Static method reference");
    
  • Instance method on parameter objects:
    Finder finder = (s1, s2) -> s1.indexOf(s2);
    
    By using method reference
    Finder finder = String::indexOf;
    
  • Instance method:
    StringConverter stringConverter = new StringConverter();
    
    Deserializer des = stringConverter::convertToInt;
    
  • Constructor:
    It is possible to refer a constructor of a class. We can do that by using ::new as like the following example. Here the functional interface is like
        public interface Factory {
                public String create(char[] val);
        }
    
    Using regular lambda
    Factory factory = chars -> new String(chars);
    
    Using constructor reference
    Factory factory = String::new;
    

References:

No comments:

Post a Comment