Showing posts with label Java lambda expressions. Show all posts
Showing posts with label Java lambda expressions. Show all posts

Friday, May 17, 2024

@FunctionalInterface Annotation in Java

In the post Functional Interfaces in Java we have already seen that functional interfaces are those interfaces that have only one abstract method. Java 8 also introduced an annotation @FunctionalInterface to be used with functional interfaces. Annotating an interface with @FunctionalInterface in Java indicates that an interface type declaration is intended to be a functional interface.

It is not mandatory to mark functional interface with @FunctionalInterface annotation, it is more of a best practice to do that and also gives a surety that no other abstract method will be added accidentally to the functional interface. It will result in a compile time error if any other abstract method is added to a functional interface which is annotated with @FunctionalInterface annotation.

Let's see it with some examples what is permitted and what is not with @FunctionalInterface annotation in Java.
First there is an example of a valid functional interface that is annotated with @FunctionalInterface-

 
@FunctionalInterface
public interface IMyFuncInterface {
  public void getValue();
}

In an interface annotated with @FunctionalInterface, if more than one abstract method is defined it results in compile time error.

@FunctionalInterface
public interface IMyFuncInterface {
  public void getValue();
  // Second abstract method so compiler error
  public void setValue();
}

Note that in Java 8 default methods and static methods are also added in interface which means interface can have a method with default implementation and static methods in Java 8. In a functional interface there may be one or more default methods/static methods but there should be only one abstract method. It is ok to have a functional interface like following.

 
@FunctionalInterface
public interface IMyFuncInterface {
  int func(int num1, int num2);
  // default method
  default int getValue(){
    return 0;
  }    
}

A functional interface can specify Object class public methods too in addition to the abstract method. That interface will still be a valid functional interface. The public Object methods are considered implicit members of a functional interface as they are automatically implemented by an instance of functional interface.

As example- This is a valid functional interface

@FunctionalInterface
interface IFuncInt {
  int func(int num1, int num2);
  // default method
  default int getValue(){
    return 0;
  }
  public String toString();
  public boolean equals(Object o);
}

That's all for this topic @FunctionalInterface Annotation in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Lambda Expressions in Java 8
  2. How to Fix The Target Type of This Expression Must be a Functional Interface Error
  3. Method Reference in Java 8
  4. Java Lambda Expression as Method Parameter
  5. Java Lambda Expressions Interview Questions And Answers

You may also like-

  1. Fail-Fast Vs Fail-Safe Iterator in Java
  2. How to Iterate a HashMap of ArrayLists of String in Java
  3. strictfp in Java
  4. static Import in Java With Examples
  5. Synchronization in Java - Synchronized Method And Block
  6. Deadlock in Java Multi-Threading
  7. Difference Between Checked And Unchecked Exceptions in Java
  8. Externalizable Interface in Java

Tuesday, April 30, 2024

Pre-defined Functional Interfaces in Java

We saw in the post Functional Interfaces in Java how you can create your own functional interface and also annotate it using @FunctionalInterface Annotation. Though it is not always required that you have to create your own functional interface for each scenario, Java has introduced a new package java.util.function that defines many general purpose pre-defined functional interfaces used by many Java libraries like Collection framework, Java Stream API and used by user code as well. In this post we’ll go through these built-in functional interfaces in Java so you have a good idea which functional interface to use in which context while using with Lambda expressions in Java.


Pre-defined functional interfaces categorization

Functional interfaces defined in java.util.function package can be categorized into five types-

  1. Consumer- Consumes the passed argument and no value is returned.
  2. Supplier- Takes no argument and supplies a result.
  3. Function- Takes argument and returns a result.
  4. Predicate- Takes argument and returns a boolean result (true or false).
  5. Operators- Functional interfaces categorized under Operator are specialized Function where the passed argument and result are of the same type.

Consumer functional interface

Consumer<T> represents a function that accepts a single input argument and returns no result. Consumer functional interface definition is as given below consisting of an abstract method accept() and a default method andThen()-

@FunctionalInterface
public interface Consumer<T> {
  void accept(T t);
  default Consumer<T> andThen(Consumer<? super T> after) {
    Objects.requireNonNull(after);
    return (T t) -> { accept(t); after.accept(t); };
  }
}

Following pre-defined Consumer functional interfaces are categorized as Consumer as all of these interfaces have the same behavior of consuming the passed value(s) and returning no result. You can use any of these based on number of arguments or data type.

  • BiConsumer<T,U>- Represents an operation that accepts two input arguments and returns no result.
  • DoubleConsumer- Represents an operation that accepts a single double-valued argument and returns no result.
  • IntConsumer- Represents an operation that accepts a single int-valued argument and returns no result.
  • LongConsumer- Represents an operation that accepts a single long-valued argument and returns no result.
  • ObjDoubleConsumer<T>- Represents an operation that accepts an object-valued and a double-valued argument, and returns no result.
  • ObjIntConsumer<T>- Represents an operation that accepts an object-valued and a int-valued argument, and returns no result.
  • ObjLongConsumer<T>- Represents an operation that accepts an object-valued and a long-valued argument, and returns no result.

Consumer functional interface Java example

In the example elements of List are displayed by using an implementation of Consumer functional interface.

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class ConsumerExample {
  public static void main(String[] args) {
    Consumer<String> consumer = s -> System.out.println(s);
    List<String> alphaList = Arrays.asList("A", "B", "C", "D");
    for(String str : alphaList) {
      // functional interface accept() method called
      consumer.accept(str);
    }
  }
}

Output

A
B
C
D

Supplier functional interface

Supplier<T> represents a function that doesn't take argument and supplies a result. Supplier functional interface definition is as given below consisting of an abstract method get()-

@FunctionalInterface
public interface Supplier<T> {
  T get();
}

Following pre-defined Supplier functional interfaces are categorized as Supplier as all of these interfaces have the same behavior of supplying a result.

  • BooleanSupplier- Represents a supplier of boolean-valued results.
  • DoubleSupplier- Represents a supplier of double-valued results.
  • IntSupplier- Represents a supplier of int-valued results.
  • LongSupplier- Represents a supplier of long-valued results.

Supplier functional interface Java example

In the example Supplier functional interface is implemented as a lambda expression to supply current date and time.

import java.time.LocalDateTime;
import java.util.function.Supplier;

public class SupplierExample {
  public static void main(String[] args) {
    Supplier<LocalDateTime> currDateTime = () -> LocalDateTime.now();
    System.out.println(currDateTime.get());
  }
}

Function functional interface

Function<T,R> represents a function that accepts one argument and produces a result. Function functional interface definition is as given below consisting of an abstract method apply(), two default methods compose(), andThen() and a static method identity().

@FunctionalInterface
public interface Function<T, R> {

  R apply(T t);

  default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
    Objects.requireNonNull(before);
    return (V v) -> apply(before.apply(v));
  }

  default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
    Objects.requireNonNull(after);
    return (T t) -> after.apply(apply(t));
  }
  static <T> Function<T, T> identity() {
    return t -> t;
  }
}

Following pre-defined Function functional interfaces are categorized as Function as all of these interfaces have the same behavior of accepting argument(s) and producing a result.

  • BiFunction<T,U,R>- Represents a function that accepts two arguments and produces a result.
  • DoubleFunction<R>- Represents a function that accepts a double-valued argument and produces a result.
  • DoubleToIntFunction- Represents a function that accepts a double-valued argument and produces an int-valued result.
  • DoubleToLongFunction- Represents a function that accepts a double-valued argument and produces a long-valued result.
  • IntFunction<R>- Represents a function that accepts an int-valued argument and produces a result.
  • IntToDoubleFunction- Represents a function that accepts an int-valued argument and produces a double-valued result.
  • IntToLongFunction- Represents a function that accepts an int-valued argument and produces a long-valued result.
  • LongFunction<R>- Represents a function that accepts a long-valued argument and produces a result.
  • LongToDoubleFunction- Represents a function that accepts a long-valued argument and produces a double-valued result.
  • LongToIntFunction- Represents a function that accepts a long-valued argument and produces an int-valued result.
  • ToDoubleBiFunction<T,U>- Represents a function that accepts two arguments and produces a double-valued result.
  • ToDoubleFunction<T>- Represents a function that produces a double-valued result.
  • ToIntBiFunction<T,U>- Represents a function that accepts two arguments and produces an int-valued result.
  • ToIntFunction<T>- Represents a function that produces an int-valued result.
  • ToLongBiFunction<T,U>- Represents a function that accepts two arguments and produces a long-valued result.
  • ToLongFunction<T>- Represents a function that produces a long-valued result.

Function functional interface Java example

In the example a Function interface is implemented to return the length of the passed String.

import java.util.function.Function;

public class FunctionExample {
  public static void main(String[] args) {
    Function<String, Integer> function = (s) -> s.length();
    System.out.println("Length of String- " + function.apply("Interface"));
  }
}

Output

Length of String- 9

Predicate functional interface

Predicate<T> represents a function that accepts one argument and produces a boolean result. Abstract method in the Predicate functional interface is boolean test(T t).

Following pre-defined Predicate functional interfaces are categorized as Predicate as all of these interfaces have the same behavior of accepting argument(s) and producing a boolean result.

  • BiPredicate<T,U>- Represents a predicate (boolean-valued function) of two arguments.
  • DoublePredicate- Represents a predicate (boolean-valued function) of one double-valued argument.
  • IntPredicate- Represents a predicate (boolean-valued function) of one int-valued argument.
  • LongPredicate- Represents a predicate (boolean-valued function) of one long-valued argument.

Predicate functional interface Java Example

In the example a number is passed and true is returned if number is even otherwise odd is retuned.

import java.util.function.Predicate;

public class PredicateExample {
  public static void main(String[] args) {
    Predicate<Integer> predicate = (n) -> n%2 == 0;
    boolean val = predicate.test(6);
    System.out.println("Is Even- " + val);    
    System.out.println("Is Even- " + predicate.test(11));
  }
}

Output

Is Even- true
Is Even- false

Operator functional interfaces

Operator functional interfaces are specialized Function interfaces that always return the value of same type as the passed arguments. Operator functional interfaces extend their Function interface counterpart like UnaryOperator extends Function and BinaryOperator extends BiFunction.

Following pre-defined Operator functional interfaces are there that can be used in place of Function interfaces if returned value is same as the type of the passed argument(s).

  • BinaryOperator<T>- Represents an operation upon two operands of the same type, producing a result of the same type as the operands.
  • DoubleBinaryOperator- Represents an operation upon two double-valued operands and producing a double-valued result.
  • DoubleUnaryOperator- Represents an operation on a single double-valued operand that produces a double-valued result.
  • IntBinaryOperator- Represents an operation upon two int-valued operands and producing an int-valued result.
  • IntUnaryOperator- Represents an operation on a single int-valued operand that produces an int-valued result.
  • LongBinaryOperator- Represents an operation upon two long-valued operands and producing a long-valued result.
  • LongUnaryOperator- Represents an operation on a single long-valued operand that produces a long-valued result.
  • UnaryOperator<T>- Represents an operation on a single operand that produces a result of the same type as its operand.

UnaryOperator functional interface Java example

In the example UnaryOperator is implemented to return the square of the passed integer.

import java.util.function.UnaryOperator;

public class UnaryOperatorExample {
  public static void main(String[] args) {
    UnaryOperator<Integer> unaryOperator = (n) -> n*n;
    System.out.println("4 squared is- " + unaryOperator.apply(4));
    System.out.println("7 squared is- " + unaryOperator.apply(7));
  }
}

Output

4 squared is- 16
7 squared is- 49

That's all for this topic Pre-defined Functional Interfaces in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Exception Handling in Java Lambda Expressions
  2. Method Reference in Java
  3. How to Fix The Target Type of This Expression Must be a Functional Interface Error
  4. Java Stream API Tutorial
  5. Java Lambda Expressions Interview Questions And Answers

You may also like-

  1. Java Stream flatMap() Method
  2. Java Lambda Expression Callable Example
  3. Invoke Method at Runtime Using Java Reflection API
  4. LinkedHashMap in Java With Examples
  5. java.lang.ClassCastException - Resolving ClassCastException in Java
  6. Java String Search Using indexOf(), lastIndexOf() And contains() Methods
  7. BeanFactoryAware Interface in Spring Framework
  8. Angular Two-Way Data Binding With Examples

Thursday, April 18, 2024

Functional Interfaces in Java

A functional interface in Java is an interface with only one abstract method. A functional interface is also known as SAM type where SAM stands for (Single Abstract Method). An example of functional interface with in Java would be Runnable interface which has only one method run().


Java functional interface example

interface IMyInterface {
  int getValue();
}

In interface IMyInterface there is only single abstract method getValue() (note that in an interface methods are implicitly abstract).

Thursday, June 15, 2023

Lambda Expressions in Java 8

Lambda expressions in Java (also known as closures) are one of the most important feature added in Java 8. Java lambda expressions provide a clear and elegant way to represent a single abstract method interface (Functional interface) using an expression.


What is a functional interface

In order to know Lambda expressions better it is very important to have a good understanding of two terms- lambda expression itself and functional interface. Here is a little primer about functional interfaces.

A functional interface is an interface with only one abstract method. A functional interface is also known as SAM type where SAM stands for (Single Abstract Method). An example of functional interface would be Runnable interface which has only one method run().

Please note that from Java 8 it is possible for an interface to have default methods and static methods thus the stress on "only one abstract method".

Also a new annotation @FunctionalInterface has been added in Java 8, all the functional interfaces can be annotated with this annotation to ensure that they have only single abstract method.

functional interface Example

interface IMyInterface {
  int getValue();
}

In interface IMyInterface there is a single abstract method getValue() (note that in an interface methods are implicitly abstract).

See Functional Interfaces in Java for detailed post about functional interfaces.

Java lambda expressions

Lambda expression in Java is an instance of a functional interface and provides implementation of the single abstract method defined by the functional interface.

Lambda Expression Syntax

A new operator has been introduced in Java for Lambda expressions.

(arg1, arg2, ..) -> body

Here you can see a new arrow operator (->) or lambda operator which divides the lambda expression into two parts.

Left side specifies parameters required by the lambda expression. Parameters are optional, if no parameters are needed an empty parenthesis can be given. Even type of the parameters is not required as compiler, in most of the cases, is able to infer type of the parameters from the context in which it is used.

Right side known as lambda body specifies the logic of the lambda expression.

Why Lambda expressions in Java

Now when we have an idea about lambda expressions and functional interfaces let's try to understand how does lambda expressions help in making your code more compact.

Most used use case for anonymous class is to implement an interface that contains only one method. This is usually done when you are trying to pass functionality as an argument to another method.

For example if you have a List of objects of type Person and you want to sort them on the basis of first name using a Comparator. In that case you need to implement compare() method of the Comparator interface. Usually that is done by implementing Comparator as an anonnymous class. So what you are doing is to pass the functionality to compare objects as an argument to Collections.sort() method.

Collections.sort(personList, new Comparator<Person>() {
  public int compare(Person a, Person b) {
    return a.getFirstName().compareTo(b.getFirstName());
  }
});
Java lambda expression also enables you to do the same thing like-
  • Passing functionality as method argument.
  • Passing code as data.

Lambda expressions can only be used to implement functional interfaces (interface with single abstract method) and lambda expressions let you express these instances of single-method classes more compactly than by using anonymous class.

For example if you have to implement the same Comparator as used above as a lambda expression then it can be done more compactly as-

Collections.sort(personList, (Person a, Person b) -> 
            a.getFirstName().compareTo(b.getFirstName()));
Type can be inferred from the surrounding context so you don't even need to define the type of the parameters.
Collections.sort(personList, (a, b) -> 
            a.getFirstName().compareTo(b.getFirstName()));

Here you can see that the functionality for sorting (implementation of compare method of the Comparator) is passed as method argument.

Java lambda expression examples

Let's see some examples of the lambda expressions in Java-

1. A very simple lambda expression.

() -> 7; 

This lambda expression takes no parameter, that's why empty parenthesis and returns the constant value 7.

If we have to write the equivalent Java method then it will be something like this-

int getValue(){
  return 7;
}

2. Lambda expressions with 2 parameters.

// concatenating two strings, it has 2 string parameters
// and they are concatenated in lambda body
(String s1, String s2) -> s1+s2;

3. Lambda expression to test if the given number is odd or not.

// Lambda expression to test if the given number is odd or not
n -> n % 2 != 0;

4. Lambda expression to display passed argument.

// Prints the passed string s to the console and returns void
(String s) -> { System.out.println(s); };

5. Complete Java Lambda expression example.

interface IMyInterface {
  int getValue();
}

public class LambdaExpressionDemo {
  public static void main(String[] args) {
    // reference of the interface
    IMyInterface objRef;
    // Lambda expression
    objRef = () -> 7;
    System.out.println("Value is " + objRef.getValue());
    // Another lambda expression using the same interface reference 
    objRef = () -> 7 * 5;
    System.out.println("Value is " + objRef.getValue());
    // This line will give compiler error as target type 
    // can't be inferred 
    objref = () -> "11";
  }
}

Output

Value is 7
Value is 35

Here we have an interface IMyInterface with one method getValue() whose return type is int. Since there is only one abstract method in the interface so IMyInterface is a functional interface.

In this program it can be seen how lambda expression () -> 7 is compatible with the abstract method. Return type is int and there is no method parameter.
If you uncomment the line () -> "11"; it will give compiler error The target type of this expression must be a functional interface as in this case return type is string which is not compatible with the return type of the abstract method, lambda expression is implementing.

Also notice that the same functional interface reference is used to execute 2 lambda expressions
objRef = () -> 7; and objRef = () -> 7 * 5;
Since both of the lambda expressions are compatible with the target type so both of them can be assigned to the same reference (Does it remind you of run time polymorphism?). That's why Lambda Expression is a Poly Expression.

6. Java Lambda expression with a parameter example.

interface IMyInterface {
  boolean test(int n);
}

public class LambdaExpressionDemo {
  public static void main(String[] args) {
    IMyInterface objRef;
    // Lambda expression
    objRef = n -> (n % 2) == 0;
    System.out.println("4 is even " + objRef.test(4)); 
    System.out.println("3 is even " + objRef.test(3)); 
  }
}

Output

4 is even true
3 is even false

Here we need to note certain points-

n -> (n % 2) == 0;

In this lambda expression type is not specified explicitly as int, type is inferred from the context in which the lambda expression is executed, though type can be given explicitly too.

int n -> (n % 2) == 0;

This lambda expression is also valid.

Also parenthesis around the parameter is omitted, in case of single parameter it is not necessary to enclose the parameter with parenthesis. Again it won't be invalid to do that, so (n) -> (n % 2) == 0; or (int n) -> (n % 2) == 0; both are valid.

In case of more than one parameter too type can be inferred so
(int x, int y) -> x+y; or (x, y) -> x + y;
both of these are valid if used in a correct context.

One important point here is we can't have lambda expression where type for only one of the parameter is explicitly declared.

// Invalid lambda expression
(int x, y) -> x + y; 

See Lambda Expression Examples in Java for more examples of lambda expression.

Target type of Lambda expressions in Java

Lambda expression is an instance of the functional interface thus the functional interface specifies its target type.

Lambda supports "target typing" which infers the object type from the context in which it is used. To infer that object type from the context-

  • The parameter type of the abstract method and the parameter type of the lambda expression must be compatible. For Example, if the abstract method in the functional interface specifies one int parameter, then the lambda should also have one int parameter explicitly defined or implicitly inferred as int by the context.
  • Its return type must be compatible with the method's type.
  • Lambda expression can throw only those exceptions which are acceptable to the method.

Target typing is used in a number of contexts including the following-

  • Variable declarations
  • Assignments
  • Return statements
  • Array initializers
  • Method or constructor arguments
  • Lambda expression bodies

Block lambda expression in Java

Till now all the examples we have seen are single expression lambda, we also have a second type of lambda expressions known as "block lambda" where the right side of the lambda expression is a block of code.

Let's see an example, here with in the lambda expression we have a block of code for counting the words in a string without using any String function.

@FunctionalInterface
interface IMyInterface {
  int doCount(String str);
}

public class LambdaExpressionDemo {
  public static void main(String[] args) {
    // Lambda expression
    IMyInterface objRef = (str) -> {
      int c = 0;
      char ch[]= new char[str.length()];
      for(int i = 0; i < str.length(); i++){
          ch[i] = str.charAt(i);
          if(((i > 0) && (ch[i] != ' ') && (ch[i-1] == ' ')) || 
          ((ch[0] != ' ') && (i == 0)))
              c++;
      }
      return c;
    };    
    System.out.println("Words in the string " + objRef.doCount("Lambda Expression in Java"));    
  }
}

Output

Words in the string 4

Note here that functional interface is annotated with a @FunctionalInterface annotation, this is a new annotation added in Java 8 to be used with functional interface.

See Functional interface annotation in Java 8 for detailed post about @FunctionalInterface annotation.

Points to note-

  • Lambda expression is an instance of a functional interface and provides implementation of the single abstract method defined by the functional interface.
  • The lambda expression signature must be the same as the functional interface method's signature, as the target type of the lambda expression is inferred from that context.
  • A lambda expression can throw only those exceptions or the subtype of the exceptions for which an exception type is declared in the functional interface method's throws clause.
  • The parameter list of the lambda expression can declare a vararg parameter: (int ... i) -> {};
  • A Lambda Expression Is a Poly Expression- The type of a lambda expression is inferred from the target type thus the same lambda expression could have different types in different contexts. Such an expression is called a poly expression.

That's all for this topic Lambda Expressions in Java 8. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Java Lambda Expression as Method Parameter
  2. Java Lambda Expression And Variable Scope
  3. Method Reference in Java
  4. Java Stream API Tutorial
  5. Java Lambda Expressions Interview Questions And Answers

You may also like-

  1. How to Fix The Target Type of This Expression Must be a Functional Interface Error
  2. How to Resolve Local Variable Defined in an Enclosing Scope Must be Final or Effectively Final Error
  3. Java Exception Handling Tutorial
  4. Multi-Catch Statement in Java Exception Handling
  5. Covariant Return Type in Java
  6. static Import in Java With Examples
  7. How HashMap Works Internally in Java
  8. Difference Between yield And sleep in Java Multi-Threading

Sunday, December 11, 2022

Lambda Expression Examples in Java

As we have already seen in the post about Java lambda expressions, they implement the abstract method of the functional interface. In that way lambda expressions can provide a compact and easy to read code which is not repetitive by using them in place of anonymous classes.

Using functional interfaces with anonymous inner classes is a common pattern in Java, from Java 8 lambda expressions provide a better alternative by implementing the abstract method of the functional interface.

In this post we'll see some examples of lambda expressions in Java like Runnable as lambda expression, Comparator as lambda expression, lambda expression implementation of Predicate functional interface.

Runnable as Lambda expression example

It is very common to implement the run() method of Runnable interface as an anonymous class, now same can be done with lambda expression in fewer lines increasing readability.

public class RunnableLambda {
  public static void main(String[] args) {
    // Runnable using anonymous class
    new Thread(new Runnable() {
      @Override
      public void run() {
        System.out.println("Runnable with anonymous");
      }
    }).start();
    
    // Runnable using lambda
    new Thread(()->System.out.println("Runnable Lambda")).start();
  }
}

It can be seen how concise the implementation becomes with lambda expression.

Comparator as Lambda expression example

In this example we'll have a list of Person object and they are sorted on first name using Comparator.

Person class

public class Person {
  private String firstName;
  private String lastName;
  private int age;
  private char gender;
  Person(String firstName, String lastName, int age, char gender){
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
    this.gender = gender;
  }
    
  public String getFirstName() {
    return firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public int getAge() {
    return age;
  }
  public char getGender() {
    return gender;
  }
    
  public String toString(){
    StringBuffer sb = new StringBuffer();
    sb.append(getFirstName()).append(" ");
    sb.append(getLastName()).append(" ");
    sb.append(getAge()).append(" ");
    sb.append(getGender());
    return sb.toString();    
  }
}
// Functional interface
@FunctionalInterface
interface IMyInterface {
  Person getRef(String firstName, String lastName, int age, char gender);
}

public class LambdaExpressionDemo {
  public static void main(String[] args) {
    List<Person> personList = createList();
    
    // comparator implementation as anonymous class
    // and sorting the list element on the basis of first name
    Collections.sort(personList, new Comparator<Person>() {
      public int compare(Person a, Person b) {
        return a.getFirstName().compareTo(b.getFirstName());
      }
    });
        
    System.out.println("Sorted list with anonymous implementation");
    for(Person p : personList){
      System.out.print(p.getFirstName() + " ");
    }
        
    // creating the same list again to use with lambda expression
    personList = createList();
    // Providing the comparator functional interface compare
    /// method as lambda exression
    Collections.sort(personList, (Person a, Person b) -> 
        a.getFirstName().compareTo(b.getFirstName()));
    System.out.println("Sorted list with lambda implementation");
    // Using the new ForEach loop of Java 8 
    // used with lambda expression
    personList.forEach((per) -> System.out.print(per.getFirstName() + " "));
  }
    
  // Utitlity method to create list
  private static List<Person> createList(){
    List<Person> tempList = new ArrayList<Person>();
    IMyInterface createObj = Person::new;
    Person person = createObj.getRef("Ram","Tiwari", 50, 'M');
    tempList.add(person);
    person = createObj.getRef("Prem", "Chopra", 13, 'M');
    tempList.add(person);
    person = createObj.getRef("Tanuja", "Trivedi", 30, 'F');
    tempList.add(person);
    person = createObj.getRef("Manoj", "Sharma", 40, 'M');
    tempList.add(person);
    System.out.println("List elements are - ");
    System.out.println(tempList);
    return tempList;
  }
}

Output

List elements are - 
[Ram Tiwari 50 M, Prem Chopra 13 M, Tanuja Trivedi 30 F, Manoj Sharma 40 M]
Sorted list with anonymous implementation
Manoj Prem Ram Tanuja List elements are - 
[Ram Tiwari 50 M, Prem Chopra 13 M, Tanuja Trivedi 30 F, Manoj Sharma 40 M]
Sorted list with lambda implementation
Manoj Prem Ram Tanuja

Here I have used some of the features of Java 8 like Constructor reference using Double colon operator, which is this line IMyInterface createObj = Person::new;

Also used the new forEach statement in Java 8 with lambda expression, which is this line-

personList.forEach((per) -> System.out.print(per.getFirstName() + " "));

Same way lambda expression can be used with other functional interfaces like Callable, ActionListener etc.

Lambda expression with inbuilt functional interfaces

With Java 8 many new functional interfaces are being defined, in fact there is a whole new package java.util.function added with many functional interfaces. The interfaces in this package are general purpose functional interfaces used by the JDK, and are available to be used by user code as well.

The following are some of the examples of new functional interfaces in Java 8-

public interface Predicate<T> {
  boolean test(T t);
}
 
public interface Function<T,R> {
  R apply(T t);
}
 
public interface BinaryOperator<T> {
  T apply(T left, T right);
}
 
public interface Consumer<T> {
  void accept(T t);
}
 
public interface Supplier<T> {
  T get();
}

Starting with Java 8 these functional interfaces can be implemented by means of lambda expressions and method references.

We have already seen in the above examples how using lambda expressions we can solve the vertical problem associated with anonymous classes and make the code concise and more readable. Here let's see an example using one of the inbuilt functional interface.

Predicate functional interface as Lambda expression implementation

Supposing we want to use inbuilt functional interface named Predicate declared as follows:

public interface Predicate<T> {
  boolean test(T t);
}

We have a class person and using that person list we want to implement a search criteria where we want to search and print the following-

  1. List of drivers (age >= 16)
  2. List of voters (age >= 18)
  3. List of senior citizens (age >= 60)

We'll use the inbuilt functional interface Predicate to set up the search criteria. Note that we don’t need to explicitly write the Predicate interface as it is already available, we just need to import it from java.util.function package.

Person Class

public class Person {
  private String firstName;
  private String lastName;
  private int age;
  private char gender;
  public Person(String firstName, String lastName, int age, char gender){
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
    this.gender = gender;
  }
    
  public String getFirstName() {
    return firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public int getAge() {
    return age;
  }
  public char getGender() {
    return gender;
  }
    
  public String toString(){
    StringBuffer sb = new StringBuffer();
    sb.append(getFirstName()).append(" ");
    sb.append(getLastName()).append(" ");
    sb.append(getAge()).append(" ");
    sb.append(getGender());
    return sb.toString();    
  }
}
@FunctionalInterface
interface IMyFunc {
  Person getRef(String firstName, String lastName, int age, char gender);
}

public class LambdaDemo {
    
  public static void main(String args[]){
    List<Person> personList = createList();
    ListPerson listPerson = new ListPerson();
    //Predicates
    // For age >= 16
    Predicate<Person> allDrivers = p -> p.getAge() >= 16;
    // For age >= 18
    Predicate<Person> allVoters = p -> p.getAge() >= 18;
    // For age >= 60
    Predicate<Person> allSeniorCitizens = p -> p.getAge() >= 60;
    // calling method to list drivers, passing predicate as arg
    listPerson.listDrivers(personList, allDrivers);
    
    // calling method to list voters, passing predicate as arg 
    listPerson.listVoters(personList, allVoters);
    
    // calling method to list senior citizens, passing predicate as arg 
    listPerson.listSeniorCitizens(personList, allSeniorCitizens);       
  }
    
  // Utitlity method to create list
  private static List<Person> createList(){
    List<Person> tempList = new ArrayList<Person>();
    // Constructor reference
    IMyFunc createObj = Person::new;
    Person person = createObj.getRef("Ram","Tiwari", 50, 'M');
    tempList.add(person);
    person = createObj.getRef("Prem", "Chopra", 13, 'M');
    tempList.add(person);
    person = createObj.getRef("Tanuja", "Trivedi", 30, 'F');
    tempList.add(person);
    person = createObj.getRef("Manoj", "Sharma", 40, 'M');
    tempList.add(person);
    person = createObj.getRef("John", "Trevor", 70, 'M');
    tempList.add(person);
    person = createObj.getRef("Alicia", "Sliver", 17, 'F');
    tempList.add(person);
    System.out.println("List elements are - ");
    System.out.println(tempList);
    return tempList;
  }
}

class ListPerson {
  // method to list drivers
  public void listDrivers(List<Person> personList, Predicate<Person> pred){
    List<Person> driverList = new ArrayList<Person>();
    for(Person person : personList){
      if (pred.test(person)){
        driverList.add(person);    
      }
    }
    System.out.println("List of drivers ");
    printList(driverList);
  }
    
  // method to list voters
  public void listVoters(List<Person> personList, Predicate<Person> pred){
    List<Person> voterList = new ArrayList<Person>();
    for(Person person : personList){
      if (pred.test(person)){
        voterList.add(person);    
      }
    }
    System.out.println("List of voters ");
    printList(voterList);
  }
    
  // method to list senior citizens
  public void listSeniorCitizens(List<Person> personList, Predicate<Person> pred){
    List<Person> seniorCitizenList = new ArrayList<Person>();
    for(Person person : personList){
      if (pred.test(person)){
        seniorCitizenList.add(person);    
      }
    }
    System.out.println("List of senior citizens ");
    printList(seniorCitizenList);
  }
 
  // Method used for printing the lists
  private void printList(List<Person> personList){
    personList.forEach((p) -> System.out.print(" FirstName - " + p.getFirstName()  
            + " LastName - " + p.getLastName() + " Age - " + p.getAge()));
    System.out.println("");
  }
}

It can be seen how concise and readable the code becomes and it is also non-repetitive, if we were using anonymous classes to write these search criteria we would have done the same chore of taking new instance of interface Predicate and overriding the test method for each search criteria. The anonymous class implementation for getting the list of drivers would have looked like this.

listPerson.listDrivers(personList, new Predicate<Person>(){
   @Override
   public boolean test(Person p){
       return p.getAge() >=16;
   }
});

So it can be seen how lambda expression can help with solving the vertical problem associated with anonymous class and provides a better alternative to provide implementation of functional interfaces.

That's all for this topic Lambda Expression Examples in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Functional Interface Annotation in Java
  2. Method Reference in Java
  3. How to Resolve Local Variable Defined in an Enclosing Scope Must be Final or Effectively Final Error
  4. Java Lambda Expression And Variable Scope
  5. Java Lambda Expressions Interview Questions And Answers

You may also like-

  1. How HashMap Works Internally in Java
  2. Executor And ExecutorService in Java With Examples
  3. final Vs finally Vs finalize in Java
  4. Difference Between throw And throws in Java
  5. static Method Overloading or Overriding in Java
  6. Covariant Return Type in Java
  7. Effectively Final in Java 8
  8. Interface Default Methods in Java 8

Monday, December 5, 2022

How to Resolve Local Variable Defined in an Enclosing Scope Must be Final or Effectively Final Error

This post talks about how to resolve "local variable defined in an enclosing scope must be final or effectively final" error while trying to write a lambda expression in Java.

Let's first get some background on what is effectively final; that will help you to get an idea why this error is coming.

Effectively Final in Java

When a lambda expression uses an assigned local variable from its enclosing space there is an important restriction.
A lambda expression may only use local variable whose value doesn't change. That restriction is referred as "variable capture" which is described as; lambda expression capture values, not variables. The local variables that a lambda expression may use are known as "effectively final".

An effectively final variable is one whose value does not change after it is first assigned. There is no need to explicitly declare such a variable as final, although doing so would not be an error. Since there is no need to explicitly declare such a variable as final thus the name effectively final. If there is an attempt to change such a variable, anyway compiler will throw an error.

Let's see it with an example. Here I have a functional interface IFunc which has a single abstract method display. Since it has a single abstract method it is a functional interface and lambda expression can be used to implement this functional interface. Just to make it clear I have also used the @Functional interface annotation.

In the code lambda expression that implements the display method of the interface just prints the value of the local variable on the console. It can be noted that there is no need to declare variable i as final which was a requirement before Java 8 (in case of anonymous class).

@FunctionalInterface
interface IFunc{
  void display();
}

public class InnerDemo { 
  public static void main(String[] args) {
    int i = 7;
    // lambda expression that implements the display method 
    // of the IFunc functional interface 
    IFunc ifunc = ()-> System.out.println("Value of i is " + i);
    // Calling the display method
    ifunc.display();
  }   
}

Output

Value of i is 7

It can be seen if we are not changing the value of local variable i, it can be used with lambda expression and there is no need to declare i as final.

When will it give error

As already pointed out while discussing effectively final "A lambda expression may only use local variable whose value doesn't change". So if you try to change the value of i with in the lambda expression you'll get the error "Local variable i defined in an enclosing scope must be final or effectively final".

Code that gives compiler error

@FunctionalInterface
interface  IFunc{
  void display();
}

public class InnerDemo {
  public static void main(String[] args) {
    int i = 7;
    // lambda expression that implements the display method 
    // of the IFunc functional interface 
    IFunc ifunc = ()-> System.out.println("Value of i is " + i++);
    // Calling the display method
    ifunc.display();
  }   
}

Here I have changed the i to i++ in System.out thus the program gives compile time error "Local variable i defined in an enclosing scope must be final or effectively final".

So it should be clear by now what it means for a variable to be effectively final and why do you get this error "local variable defined in an enclosing scope must be final or effectively final".

Solution to get around this error

Since it is a rule in Java programming language that variable in an enclosing scope can't be change in inner class or lambda expression, so you can't change the value of the variable. That said, there is a get around which I have used and that get around is to use array.

If we take the previous example again by using an int[] array instead of int variable-

@FunctionalInterface
interface  IFunc{
 void display();
}

public class InnerDemo {

  public static void main(String[] args) {
    int[] numArr = {7};
    // lambda expression that implements the display method 
    // of the IFunc functional interface 
    IFunc ifunc = ()-> System.out.println("Value of i is " + (numArr[0]+1));
    // Calling the display method
    ifunc.display();
  }
}

Output

Value of i is 8

As you can see it works now and "local variable defined in an enclosing scope must be final or effectively final" error is not thrown anymore.

Works very well with boolean flags and that's where I have used it. Let's see a small example.

public class Test{
 public static void main(String[] args) {
  List applications = Arrays.asList("A", "B");
  List user = Arrays.asList("A");
  Boolean[] arr = {true}; 
  applications.forEach( a -> {
   for (String str : user) {
    if(a.equals(str)) {
     //error resolved: Local variable flag defined in an enclosing scope must be final or effectively final
     arr[0] = false; 
     break;
    }else{
     arr[0] = true;
    }
   }
 
   if(!arr[0]) {
    System.out.println("Here with false");
   }else{
    System.out.println("Here with true");
   }
  });
 }
}

Output

Here with false
Here with true

That's all for this topic How to Resolve Local Variable Defined in an Enclosing Scope Must be Final or Effectively Final Error. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Lambda Expressions in Java 8
  2. Java Lambda Expression And Variable Scope
  3. How to Fix The Target Type of This Expression Must be a Functional Interface Error
  4. Method Reference in Java
  5. Java Lambda Expressions Interview Questions And Answers

You may also like-

  1. Multi-Catch Statement in Java Exception Handling
  2. Interface Static Methods in Java
  3. Java Stream API Examples
  4. Java Abstract Class and Abstract Method
  5. final Keyword in Java With Examples
  6. Java ThreadLocal Class With Examples
  7. How and Why to Synchronize ArrayList in Java
  8. Best Practices For Exception Handling in Java

Saturday, November 26, 2022

Java Lambda Expression And Variable Scope

The body of a lambda expression in Java does not define a new scope; the lambda expression scope is the same as the enclosing scope.

Let's see it with an example, if there is already a declared variable i and lambda expression body declares a local variable i too, that will result in compiler error "Lambda expression's local variable i cannot re-declare another local variable defined in an enclosing scope"

Java lambda expression and variable scope

Effectively Final in Java

When a lambda expression uses an assigned local variable from its enclosing space there is an important restriction; Lambda expression in Java may only use local variable whose value doesn't change. That restriction is referred as "variable capture" which is described as; lambda expression capture values, not variables. The local variables that a lambda expression may use are known as effectively final.

An effectively final variable is one whose value does not change after it is first assigned. There is no need to explicitly declare such a variable as final, although doing so would not be an error.

Let's see it with an example, we have a local variable i which is initialized with the value 7, with in the lambda expression we are trying to change that value by assigning a new value to i. This will result in compiler error- "Local variable i defined in an enclosing scope must be final or effectively final"

lambda expression and variable scope

this() and super() with lambda expression in Java

this and super references with in a lambda expression are the same as in the enclosing context. Since a lambda expression does not define a new scope, the this keyword with in a lambda expression signifies the this parameter of the method where the lambda expression is residing.

@FunctionalInterface
interface IFuncInt {
  int func(int num1, int num2);
  public String toString();
}

public class LambdaVarDemo {
  public static void main(String[] args){                
    LambdaVarDemo lambdaDemo = new LambdaVarDemo();
    lambdaDemo.getResult();
  }
    
  public void getResult(){
    IFuncInt funcInt = (num1, num2) -> {
      System.out.println("calling toString " + this.toString());
      return num1 + num2;        
    };
    System.out.println("Result is " + funcInt.func(6, 7));
  }
    
  @Override
  public String toString() {
    System.out.println("in class LambdaVarDemo toString()" );
    return super.toString();
  }
}

Output

in class LambdaVarDemo toString()
calling toString org.netjs.examples1.LambdaVarDemo@12c9b19
Result is 13

Here it can be seen that the expression this.toString() calls the toString method of the LambdaVarDemo object, not the toString() method of the IFuncInt instance. Please note that a functional interface may have the Object class public methods too in addition to the abstract method.

That's all for this topic Java Lambda Expression And Variable Scope. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Lambda Expressions in Java 8
  2. Functional Interfaces in Java
  3. How to Fix The Target Type of This Expression Must be a Functional Interface Error
  4. Java Lambda Expression And Exception Handling
  5. Java Lambda Expressions Interview Questions

You may also like-

  1. Method Reference in Java
  2. How LinkedList Class Works Internally in Java
  3. How ArrayList Works Internally in Java
  4. Why wait(), notify() And notifyAll() Must be Called Inside a Synchronized Method or Block
  5. Synchronization in Java - Synchronized Method And Block
  6. Best Practices For Exception Handling in Java
  7. Java Abstract Class and Abstract Method
  8. How to Create PDF From XML Using Apache FOP

Sunday, September 18, 2022

Method Reference in Java

We generally use lambda expressions to create anonymous methods but sometimes lambda expressions are also used to call an existing method. There is another feature provided in Java 8 related to lambda expression called method reference in Java that provides a clearer alternative to refer to the existing method by name.

Important thing to note about Java method references is that they provide a way to refer to a method, they don't execute the method.

Method reference in Java relates to lambda expression as they also require a target type context and at the time of execution they also create an instance of functional interface.

How lambda expressions and method references differ is where lambda expressions let us define anonymous methods which can be used as an instance of functional interfaces. Method references do the same thing, but with existing methods.


Kinds of Method References in Java

There are four kinds of method references in Java.

Kind Example Syntax
Reference to a static method ContainingClass::staticMethodName ClassName::methodName
Reference to an instance method of a particular object containingObject::instanceMethodName objRef::methodName
Reference to an instance method of an arbitrary object of a particular type ContainingType::methodName ClassName::instanceMethodName
Reference to a constructor ClassName::new classname::new

Notice that the class name is separated from the method name by a double colon. The :: is a new separator (known as double colon operator) that has been added in Java 8.

Method References to static methods

The following example code shows a static method reference in Java. In the example there is a functional interface IMyStringFunc with a method stringFunc.

import java.util.Arrays;

@FunctionalInterface
interface IMyStringFunc<T, R>{
  R stringFunc(T t);
}
public class MethodRefDemo {
  public static void main(String[] args) {
    //String array of names
    String[] strNames = new String[]{"Ram", "shyam", "Ramesh", "John", "brad", 
           "Suresh"};
    // method reference to the static method sortName
    IMyStringFunc<String[],String[]> stringFunc = SortClass::sortName;
    // Here calling strngFunc will refer to the implementing method
    // sortName()
    String[] sortedNames = stringFunc.stringFunc(strNames);
    for(String name : sortedNames){
      System.out.println(name);
    }
  }
}

class SortClass{
  // A static method that sorts an array
  static String[] sortName(String[] names) {
    //Sorting array using sort method (case sensitive)
    Arrays.sort(names);
    return names;
  }
}

Output

John
Ram
Ramesh
Suresh
brad
shyam

In the code in this line SortClass::sortName; existing method sortName() is referred using method reference. This works because sortName is compatible with the IMyStringFunc functional interface. Thus, the expression SortClass::sortName evaluates to a reference to an object in which method sortName provides the implementation of abstract method stringFunc in functional interface IMyStringFunc.

Method References to Instance Methods

To pass a reference to an instance method of a particular object is similar to static method reference, instead of class we need to use object

objRef::methodName

Let's see the same example again with object

import java.util.Arrays;
@FunctionalInterface
interface IMyStringFunc<T, R>{
  R stringFunc(T t);
}

public class MethodRefDemo {
  public static void main(String[] args) {
    // creating an object
    SortClass sc = new SortClass();
    //String array of names
    String[] strNames = new String[]{"Ram", "shyam", "Ramesh", "John", "brad", 
            "Suresh"};  
    // method reference to the instance method sortName
    IMyStringFunc<String[],String[]> refObj = sc::sortName;
    String[] sortedNames = refObj.stringFunc(strNames);
    for(String name : sortedNames){
      System.out.println(name);
    }
  }
}

class SortClass{
  // A non-static method that sorts an array
  String[] sortName(String[] names) {
    //Sorting array using sort method (case sensitive)
    Arrays.sort(names);
    return names;
  }
}

Reference to an instance method of an arbitrary object of a particular type

There may be a situation when you want to specify an instance method that can be used with any object of a given class without any particular object. In that case name of the class is used even when a non-static method is specified.

ClassName::instanceMethodName

Let's take one example where we have a Person class and we have a list of Person object. We want to call getFirstName() method on all those person objects.

Person Class

public class Person {
  private String firstName;
  private String lastName;
  private int age;
  private char gender;
  public Person(String firstName, String lastName, int age, char gender){
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
    this.gender = gender;
  }
    
  public String getFirstName() {
    return firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public int getAge() {
    return age;
  }
  public char getGender() {
    return gender;
  }
    
  public String toString(){
    StringBuffer sb = new StringBuffer();
    sb.append(getFirstName()).append(" ");
    sb.append(getLastName()).append(" ");
    sb.append(getAge()).append(" ");
    sb.append(getGender());
    return sb.toString();      
  }
}
@FunctionalInterface
interface IMyStringFunc<T, R>{
  R stringFunc(T t);
}

public class MethodRefDemo {
  public static void main(String[] args) {
    List<Person> personList = createList();
    List allNames = MethodRefDemo.listAllNames (personList, Person::getFirstName);
    System.out.println("" + allNames);
  }
    
  //Utitlity method to create list
  private static List<Person> createList(){
    List<Person> tempList = new ArrayList<Person>();
    IMyFunc createObj = Person::new;
    Person person = createObj.getRef("Ram","Tiwari", 50, 'M');
    tempList.add(person);
    person = createObj.getRef("Prem", "Chopra", 13, 'M');
    tempList.add(person);
    person = createObj.getRef("Tanuja", "Trivedi", 30, 'F');
    tempList.add(person);
    person = createObj.getRef("Manoj", "Sharma", 40, 'M');
    tempList.add(person);
    person = createObj.getRef("John", "Trevor", 70, 'M');
    tempList.add(person);
    person = createObj.getRef("Alicia", "Sliver", 17, 'F');
    tempList.add(person);
    System.out.println("List elements are - ");
    System.out.println(tempList);
    return tempList;
  }

  private static List<String> listAllNames(List<Person> person, 
         IMyStringFunc<Person, String> func){
    List<String> result = new ArrayList<String>();
    person.forEach(x -> result.add(func.stringFunc(x)));
    return result;
  }
}

Notice this line Person::getFirstName here we are calling getFirstName method on all the objects of the list not any one particular object.

Reference to a Constructor

A constructor can be referenced in the same way as a static method by using new.

public class Person {
  private String firstName;
  private String lastName;
  private int age;
  private char gender;
  public Person(String firstName, String lastName, int age, char gender){
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
    this.gender = gender;
  }
    
  public String getFirstName() {
    return firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public int getAge() {
    return age;
  }
  public char getGender() {
    return gender;
  }
    
  public String toString(){
    StringBuffer sb = new StringBuffer();
    sb.append(getFirstName()).append(" ");
    sb.append(getLastName()).append(" ");
    sb.append(getAge()).append(" ");
    sb.append(getGender());
    return sb.toString();
  }
}
@FunctionalInterface
interface IMyFunc {
  Person getRef(String firstName, String lastName, int age, char gender);
}

public class LambdaDemo {
  public static void main(String[] args) {
    List<Person> personList = createList();
    System.out.println("Name - " + personList.get(0).getFirstName());
  }
  // Utitlity method to create list
  private static List<Person> createList(){
    List<Person> tempList = new ArrayList<Person>();
    IMyFunc createObj = Person::new;
    Person person = createObj.getRef("Ram","Tiwari", 50, 'M');
    tempList.add(person);
    person = createObj.getRef("Prem", "Chopra", 13, 'M');
    tempList.add(person);
    person = createObj.getRef("Tanuja", "Trivedi", 30, 'F');
    tempList.add(person);
    person = createObj.getRef("Manoj", "Sharma", 40, 'M');
    tempList.add(person);
    person = createObj.getRef("John", "Trevor", 70, 'M');
    tempList.add(person);
    person = createObj.getRef("Alicia", "Sliver", 17, 'F');
    tempList.add(person);
    System.out.println("List elements are - ");
    System.out.println(tempList);
    return tempList;
  }
}

Output

List elements are - 
[Ram Tiwari 50 M, Prem Chopra 13 M, Tanuja Trivedi 30 F, Manoj Sharma 40 M, John Trevor 70 M, Alicia Sliver 17 F]
Name - Ram

In the program notice that the getRef method of the IMyFunc returns a reference of type Person and has String, String, int and char as parameters. Also notice that in the Person class there is a constructor which specifies String, String, int and char as parameters.

Using this line Person::new a constructor reference to a Person constructor is created. Functional interface method also takes the same params thus the constructor of the Person class is referred through it.

That's all for this topic Method Reference in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Functional Interface Annotation in Java
  2. How to Resolve Local Variable Defined in an Enclosing Scope Must be Final or Effectively Final Error
  3. Java Lambda Expression as Method Parameter
  4. Java Lambda Expression And Variable Scope
  5. Java Lambda Expressions Interview Questions And Answers

You may also like-

  1. How HashSet Works Internally in Java
  2. equals() And hashCode() Methods in Java
  3. final Vs finally Vs finalize in Java
  4. Difference Between throw And throws in Java
  5. static Method Overloading or Overriding in Java
  6. Why wait(), notify() And notifyAll() Methods Are in Object Class And Not in Thread Class
  7. PermGen Space Removal in Java 8
  8. How to Create PDF From XML Using Apache FOP

Saturday, May 14, 2022

Java Lambda Expression Callable Example

Since Callable is a functional interface, Java 8 onward it can also be implemented as a lambda expression. This post shows how you can implement Callable interface as a lambda expression in Java.

Suppose you want to have a callable where string is passed and it returns the length of the string.
In this Java code a thread pool of 2 threads is created and then submit method is called with callable object as parameter.

Java Code

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class CallableLambda {
  public static void main(String args[]){
    ExecutorService es = Executors.newFixedThreadPool(2);
    getLength(es, "executor");
    getLength(es, "executor service");
    getLength(es, "Scheduled executor service");
    getLength(es, "executors");
    getLength(es, "fork join");
    getLength(es, "callable");    
  }
    
  public static void getLength(ExecutorService es, final String str){
    // callable implemented as lambda expression
    Callable<String> callableObj = () -> {
      StringBuffer sb = new StringBuffer();
      return (sb.append("Length of string ").append(str).append(" is ").
              append(str.length())).toString();
    };
        
    // submit method
    Future<String> f = es.submit(callableObj);
    
    try {
      System.out.println("" + f.get());
    } catch (InterruptedException | ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

Output

Length of string executor is 8
Length of string executor service is 16
Length of string Scheduled executor service is 26
Length of string executors is 9
Length of string fork join is 9
Length of string callable is 8

Also, if you noticed the  try-catch block in the code,  multi catch statement from Java 7 is used here.

That's all for this topic Java Lambda Expression Callable Example. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Programs Page


Related Topics

  1. Java Lambda Expression Runnable Example
  2. Java Lambda Expression Comparator Example
  3. Lambda Expression Examples in Java
  4. Functional Interface Annotation in Java
  5. Java Lambda Expressions Interview Questions And Answers

You may also like-

  1. How to Convert Date And Time Between Different Time-Zones in Java
  2. Java Program to Convert a File to Byte Array
  3. Java Concurrency Interview Questions And Answers
  4. Executor And ExecutorService in Java With Examples
  5. Difference Between Comparable and Comparator in Java
  6. Java join() Method - Joining Strings
  7. Interface Default Methods in Java
  8. Dependency Injection in Spring Framework

Wednesday, May 4, 2022

Java Lambda Expression Runnable Example

This post shows how to implement Runnable interface as a lambda expression when you are creating a thread in Java. Since Runnable is a functional interface, Java 8 onward it can also be implemented as a lambda expression.

Refer Lambda expressions in Java 8 to know more about Java lambda expressions.

It is very common to implement the run() method of Runnable interface as an anonymous inner class, as shown in the following code.

Runnable as an anonymous class

public class RunnableIC {
  public static void main(String[] args) {
    // Runnable using anonymous class
    new Thread(new Runnable() {
      @Override
      public void run() {
        System.out.println("Runnable as anonymous class");
      }
    }).start();      
  }
}

From Java 8 same can be done with lambda expression in fewer lines increasing readability, as shown in the following code.

Runnable as a lambda expression in Java

public class RunnableLambda {
  public static void main(String[] args) {
    // Runnable using lambda
    new Thread(()->System.out.println("Runnable as Lambda expression")).start();
  }
}
If you want to make it more obvious then you can also write it as below.
public class RunnableLambda {
  public static void main(String[] args) {
    Runnable r = ()->{System.out.println("Runnable as Lambda expression");};
    // Passing runnable instance
    new Thread(r).start();
  }
}

That's all for this topic Java Lambda Expression Runnable Example. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Programs Page


Related Topics

  1. Java Lambda Expression Comparator Example
  2. Java Lambda Expression Callable Example
  3. Functional Interface Annotation in Java
  4. How to Fix The Target Type of This Expression Must be a Functional Interface Error
  5. Java Lambda Expressions Interview Questions And Answers

You may also like-

  1. Producer-Consumer Java Program Using ArrayBlockingQueue
  2. Printing Numbers in Sequence Using Threads Java Program
  3. Convert int to String in Java
  4. Synchronization in Java - Synchronized Method And Block
  5. Java BlockingDeque With Examples
  6. Polymorphism in Java
  7. Optional Class in Java With Examples
  8. Autowiring using XML configuration in Spring