Lambda expressions (JSR-335)

Intro

Problem

Сложность решения некоторых простых задач в сравнении с функциональными языками программирования.

button.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent event) {
        System.out.println("Hello World!");
    }
});

Solution

button.addActionListener(event -> System.out.println("Hello World!"));
  • JSR-335: Lambda expressions

    • Lambda expressions

Lambda expressions

Lambda expressions

  • Анонимный блок кода со списком параметров и телом (по сути – анонимная функция)

    • (parameters) -> expressions

    • (parameters) -> { expressions; }

Functional Interface

interface Operationable {
    int calculate(int x, int y);
}

Anonymous Classes

public class LambdaApp {
    public static void main(String[] args) {
        Operationable op = new Operationable() {
            public int calculate(int x, int y) {
                return x + y;
            }
        };
        int z = op.calculate(20, 10);
        System.out.println(z);
    }
}
30

Example

public class LambdaApp {
    public static void main(String[] args) {
        Operationable operation;
        operation = (x, y) -> x + y;

        int result = operation.calculate(10, 20);
        System.out.println(result);
    }
}
30

Steps for using Lambda Expression

// Defining reference to functional interface:
Operationable operation;
// Creating Lambda Expression
operation = (x, y) -> x + y;
// Using Lambda Expression
int result = operation.calculate(10, 20);

Example

Operationable operation1 = (int x, int y) -> x + y;
Operationable operation2 = (int x, int y) -> x - y;
Operationable operation3 = (int x, int y) -> x * y;

System.out.println(operation1.calculate(20, 10));
System.out.println(operation2.calculate(20, 10));
System.out.println(operation3.calculate(20, 10));
30
10
200

Syntax Lambda Expressions

Syntax Lambda Expressions

() -> {
    return 3.1415;
}
(int a, int b) -> {
    return a + b;
}
(a, b) -> {
    return a + b;
}

Syntax Lambda Expressions

(String s) -> {
    System.out.println(s);
}
(s) -> System.out.println(s);
() -> System.out.println("Hello World");
() -> 42;

Terminal Lambda Expressions

interface Printable {
    void print(String s);
}
public class LambdaApp {
    public static void main(String[] args) {
        Printable printer = s -> System.out.println(s);
        printer.print("Hello Java!");
    }
}
Hello Java!

Lambda Expressions and global/local variables

Lambda Expressions and global variables

interface Operation {
    int calculate();
}

Lambda Expressions and global variables

public class LambdaApp {
    static int x = 10;
    static int y = 20;

    public static void main(String[] args) {
        Operation op = () -> {
            x = 30;
            return x + y;
        };
        System.out.println(op.calculate());
        System.out.println(x);
    }
}
50
30

Lambda Expressions and local variables

public static void main(String[] args) {
    int n = 70;
    int m = 30;
    Operation op = () -> {
        return m + n;
    };
    System.out.println(op.calculate());
}
100

Lambda Expressions and local variables

public static void main(String[] args) {
    int n = 70;
    int m = 30;
    Operation op = () -> {
        n = 50;
        return m + n;
    };
    System.out.println(op.calculate());
}
error: local variables referenced from a lambda expression must be final or effectively final

Lambda Expressions and local variables

public static void main(String[] args) {
    int n = 70;
    int m = 30;
    Operation op = () -> {
        return m + n;
    };
    n = 50;
    System.out.println(op.calculate());
}
error: local variables referenced from a lambda expression must be final or effectively final

Generics and Lambda

Generics and Lambda

interface Operationable<T> {
    T calculate(T x, T y);
}
public class LambdaApp {
    public static void main(String[] args) {
        Operationable<Integer> operation1 = (x, y) -> x + y;
        Operationable<String> operation2 = (x, y) -> x + y;

        System.out.println(operation1.calculate(20, 10));
        System.out.println(operation2.calculate("20", "10"));
    }
}
30
2010

Использование Lambda Expressions

Lambda as parameters method

interface Expression {
    boolean isEqual(int n);
}
public class LambdaApp {
    public static void main(String[] args) {
        Expression func = (n) -> n % 2 == 0;
        int[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        System.out.println(sum(nums, func));
    }

    private static int sum(int[] numbers, Expression func) {
        int result = 0;
        for (int i : numbers) {
            if (func.isEqual(i))
                result += i;
        }
        return result;
    }
}
20

Lambda as static method

interface Expression {
    boolean isEqual(int n);
}
class ExpressionHelper {
    static boolean isEven(int n) {
        return n % 2 == 0;
    }

    static boolean isPositive(int n) {
        return n > 0;
    }
}

Lambda as static method

public class LambdaApp {
    public static void main(String[] args) {
        int[] nums = {-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5};
        System.out.println(sum(nums, ExpressionHelper::isEven));

        Expression expr = ExpressionHelper::isPositive;
        System.out.println(sum(nums, expr));
    }

    private static int sum(int[] numbers, Expression func) {
        int result = 0;
        for (int i : numbers) {
            if (func.isEqual(i))
                result += i;
        }
        return result;
    }
}
0
15

Lambda as a result of methods

interface Operation {
    int execute(int x, int y);
}

Lambda as a result of methods

public class LambdaApp {
    public static void main(String[] args) {
        Operation func = action(1);
        int a = func.execute(6, 5);
        System.out.println(a);

        int b = action(2).execute(8, 2);
        System.out.println(b);
    }

    private static Operation action(int number) {
        switch (number) {
            case 1:
                return (x, y) -> x + y;
            case 2:
                return (x, y) -> x - y;
            case 3:
                return (x, y) -> x * y;
            default:
                return (x, y) -> 0;
        }
    }
}
11
6