Java. Lambda expressions for generic functional interfaces. Examples




Lambda expressions for generic functional interfaces. Examples


Contents


Search other websites:

1. Features of using generics (templates) in functional interfaces

The functional interface can be generic (template). In this case, the target type of the lambda expression is determined based on the type specified in the reference to that functional interface.

For example. Let the generalized functional interface IValue be given

// Generalized (template) functional interface.
// This interface operates on the generic type T.
interface IValue<T> {
  T GetValue();
}

The IValue<T> interface operates on the generic type T. The interface declares an abstract method GetValue() that returns a value of type T. Therefore, this functional interface is compatible with any lambda expression that takes one parameter and returns a value of the same type. When declaring a reference to the IValue<T> functional interface, you must specify the target type of the lambda expression in the type argument:

// Declare a reference to the IValue functional interface,
// which will operate on the Float type
IValue<Float> refIValue;

After that, you can form a lambda expression and call the GetValue() method

// Set a lambda expression with reference to the type Float
refIValue = () -> 3.1415f; // return the value of float type

// Invoke method GetValue(), which returns 3.1415f
float v = refIValue.GetValue(); // v = 3.1415

If, when forming a lambda expression, you try to return a value of another (incompatible) type

refIValue = () -> "Hello world!"; // here the type is String and not Float

then the compiler will generate an error like

Type mismatch: cannot convert from String to Float

For the lambda expression to return a String type, you must declare a new reference to the IValue interface with an argument of type String (IValue<String>).

 

2. Solutions to problems of building lambda expressions that implement generalized functional interfaces. Examples
2.1. Building a lambda expression that returns a numeric value

The example demonstrates:

  • declaration of a generic (template) functional interface IValue<T>, operating on the T type;
  • creating a lambda expression and using it for the numeric type Float. The lambda expression implements the generic IValue<T> functional interface.

 

// Generalized (template) functional interface.
// This interface operates on the generic type T.
interface IValue<T> {
  T GetValue();
}

public class TrainLambda02 {

  public static void main(String[] args) {
    // Declare a reference to the IValue functional interface
    // that will operate on the Float type
    IValue<Float> refIValue;

    // Set a lambda expression with reference to the type Float
    refIValue = () -> 3.1415f; // return the value of float type

    // Invoke method GetValue(), which returns 3.1415f
    float v = refIValue.GetValue(); // v = 3.1415
    System.out.println("v = " + v);
  }
}

The result of the program

v = 3.1415

 

2.2. Lambda expression that implements elementwise summation of arrays of numbers

Task. Develop a program in which element-wise summation of arrays of 10 numbers is carried out. The type of numbers can be any numeric (int, double, float, …). Implement array summation using a lambda expressions.

Solution. To sum two arrays of numbers, you need to implement the ISumArrays functional interface, which contains one SumArrays() method. This method must receive two parameters – arrays of numbers. The method must return a result – an array of numbers, which is the sum of two parameter arrays.

The problem statement says that the type of numbers can be any numeric (int, double, float, …). This means that you need to develop a generic (template) ISumArrays interface for some type T. Since T is restricted to numeric types, it must be restricted to Number.

In the main() function, you need to test the operation of the created functional interface.

Below is the text of the program that solves this problem.

// ISumArrays templated functional interface
interface ISumArrays<T extends Number> {
  T[] SumArrays(T[] A, T[] B);
}

// A class containing methods that implement the lambda expression
// and test the program's operation.
public class Lambda {

  public static void main(String[] args) {
    // 1. Declare ISumArrays reference for Double type
    ISumArrays<Double> ref;

    // 2. Create two arrays of double type
    Double[] A1 = { 2.5, 1.4, 0.9, 1.1, 2.7, 2.9, 1.3, 2.0, 5.5, 1.2 };
    Double[] A2 = { 1.5, 1.0, 0.6, 1.7, 0.7, 0.2, 0.3, 0.2, 1.1, 3.3 };

    // 3. Generate lambda expression for Double type
    ref = (A, B) -> {
      Double[] C = new Double[A.length]; // numeric type in arrays
      for (int i=0; i<A.length; i++)
      {
        // sum two numbers as double
        C[i] = A[i].doubleValue() + B[i].doubleValue();
      }
      return C;
    };

    // 4. Call the method of a functional interface
    Double[] A3 = (Double[])ref.SumArrays(A1, A2);

    // 5. Print the result
    System.out.print("A3: ");
    for (Double t : A3)
      System.out.print(" " + t);
    System.out.println();
  }
}

In the above code, you should pay attention to how arrays of numbers are passed to the lambda expression

...

ref = (A, B) -> {
  Double[] C = new Double[A.length]; // numeric type in arrays
  for (int i=0; i<A.length; i++)
  {
    // sum two numbers as double
    C[i] = A[i].doubleValue() + B[i].doubleValue();
  }
  return C;
};

...

Since the type of the lambda expression parameter is determined from the target context, arrays in the lambda expression are passed as A and B. The A parameter is associated with A[]. The B parameter is associated with B[].

 

2.3. Calculating the number of occurrences of a given element in an array

Task. Develop a program that demonstrates the use of a lambda expression to find an element in an array. The program should contain a generalized functional interface. Implement a lambda expression for the String type.

Solution. The text of the program that solves this problem is as follows.

// Template functional interface IFindItem
interface IFindItem<T> {
  // a method that calculates the number of occurrences
  // of a given element in an array of numbers
  int Search(T item, T[] items);
}

// A class that contains methods that implement
// a lambda expression and tests the operation of the program.
public class Lambda {

  public static void main(String[] args) {
    // 1. Declare a functional interface reference for type String
    IFindItem<String> ref;

    // 2. Define lambda expression
    ref = (item, items) -> {
      int count=0;
      for (int i=0; i<items.length; i++)
        if (item==items[i])
          count++;
      return count;
    };

    // 3. Create array of strings
    String[] AS = { "abc", "abd", "def", "acf", "abc", "afx" };

    // 4. Test lambda expression
    int count = ref.Search("abc", AS);
    System.out.println("count = " + count); // count = 2
  }
}

The result of the program

count = 2

 


Related topics