10. Lambdas

  • variable capture

10.1. Functional interface

1interface IntegerTest {
2  boolean test(int n);
3}
1IntegerTest isEven = (n) -> n % 2 == 0;
2
3var numbers = new Integer[] { 1, 2, 3, 4, 5 };
4for (var num : numbers) {
5  System.out.println(isEven.test(num));
6}

10.2. Generic functional interface

1interface NumberFormatter<T extends Number> {
2  String format(T num);
3}
1NumberFormatter formatter = (num) -> String.format("%.3f", num);
2
3var data = new Double[] { 1.22222, 3.44444, 5.823432 };
4for (var num : data) {
5  System.out.println(formatter.format(num));
6}

10.3. Block lambda

1interface StringMerger {
2  String f(String ... items);
3}
 1StringMerger classicMerger = (items) -> {
 2  String s = "";
 3  for (int i = 0; i < items.length; i++) {
 4    s += items[i];
 5    if (i < items.length - 1) {
 6      s += ",";
 7    }
 8  }
 9  return s;
10};
11
12StringMerger sbMerger = (items) -> {
13  StringBuilder sb = new StringBuilder();
14  for (int i = 0; i < items.length; i++) {
15    sb.append(items[i]);
16    if (i < items.length - 1) {
17      sb.append(',');
18    }
19  }
20  return sb.toString();
21};
22
23StringMerger backwardMerger = (items) -> {
24  String s = "";
25  for (int i = items.length - 1; i >= 0; i--) {
26    s += items[i];
27    if (i > 0) {
28      s += ",";
29    }
30  }
31  return s;
32};
33
34var tokens = new String[] { "John", "Jack", "Jake", "Joe" };
35
36System.out.println(classicMerger.f(tokens));
37System.out.println(sbMerger.f(tokens));
38System.out.println(backwardMerger.f(tokens));

10.4. Lambda as argument

1interface MathFunc {
2  int doIt(int v1, int v2);
3}
4
5static int mathOp(MathFunc f, int v1, int v2) {
6  return f.doIt(v1, v2);
7}
1MathFunc add = (v1, v2) -> v1 + v2;
2MathFunc sub = (v1, v2) -> v1 - v2;
3MathFunc mul = (v1, v2) -> v1 * v2;
4MathFunc div = (v1, v2) -> v1 / v2;
5
6System.out.println(mathOp(add, 10, 8));
7System.out.println(mathOp(sub, 10, 8));
8System.out.println(mathOp(mul, 10, 8));
9System.out.println(mathOp(div, 10, 8));

10.5. Variable capture

1interface StringOp {
2  String f(String s);
3}
 1final int max = 10;
 2StringOp op = (s) -> {
 3  StringBuilder sb = new StringBuilder();
 4  for (int i = 0; i < max; i++) {
 5    sb.append(s);
 6    if (i < max - 1) {
 7      sb.append(',');
 8    }
 9  }
10  return sb.toString();
11};
12
13System.out.println(op.f("dog"));
14System.out.println(op.f("cat"));

10.6. Predefined functional interfaces

1import java.util.function.BinaryOperator;
2import java.util.function.Consumer;
3import java.util.function.Function;
4import java.util.function.Predicate;
5import java.util.function.Supplier;
6import java.util.function.UnaryOperator;
 1UnaryOperator<Integer> addOne = a -> a + 1;
 2System.out.println(addOne.apply(3));
 3
 4BinaryOperator<Integer> add = (a, b) -> a + b;
 5System.out.println(add.apply(1, 2));
 6
 7Consumer<Integer> print = a -> System.out.println(a);
 8print.accept(3);
 9
10Supplier<Double> next = () -> Math.random();
11System.out.println(next.get());
12
13Function<Double[], Double>  sum = (numbers) -> {
14  double s = 0.0d;
15  for (int i = 0; i < numbers.length; i++) {
16    s += numbers[i];
17  }
18  return s;
19};
20System.out.println(sum.apply(new Double[] { 1.0, 2.0, 3.0 }));
21
22Predicate<Integer> isEven = a -> a % 2 == 0;
23System.out.println(isEven.test(3));