Functional Programming
Lambda Expressions
Inline Functions
You need to sort users by age. Writing a separate Comparator class is verbose.
Lambda expressions let you write the comparison inline: (a, b) -> a.age - b.age.
Anonymous functions in one line.
Basic lambda
Replace anonymous class with lambda.
import java.util.*;
public class Basic {
public static void main(String[] args) {
System.out.println("No parameters:\n");
Runnable task = () -> System.out.println(" Hello from lambda!");
task.run();
Runnable oldWay = new Runnable() {
@Override
public void run() {
System.out.println(" Hello from anonymous class");
}
};
oldWay.run();
System.out.println("\nSingle parameter:");
interface Printer {
void print(String message);
}
Printer p1 = message -> System.out.println(" " + message);
p1.print("No parentheses");
Printer p2 = (message) -> System.out.println(" " + message);
p2.print("With parentheses");
System.out.println("\nMultiple parameters:");
interface Calculator {
int calculate(int a, int b);
}
Calculator add = (a, b) -> a + b;
Calculator subtract = (a, b) -> a - b;
Calculator multiply = (a, b) -> a * b;
int calcB = ;
System.out.println(" 5 + " + calcB + " = " + add.calculate(5, calcB));
System.out.println(" 5 - " + calcB + " = " + subtract.calculate(5, calcB));
System.out.println(" 5 * " + calcB + " = " + multiply.calculate(5, calcB));
System.out.println("\nBlock body:");
Calculator divide = (a, b) -> {
if (b == 0) {
System.out.println(" Error: Division by zero");
return 0;
}
return a / b;
};
System.out.println(" 10 / " + calcB + " = " + divide.calculate(10, calcB));
System.out.println("\nExplicit types:");
Calculator power = (int base, int exp) -> {
int result = 1;
for (int i = 0; i < exp; i++) {
result *= base;
}
return result;
};
System.out.println(" 2^3 = " + power.calculate(2, 3));
System.out.println(" 5^2 = " + power.calculate(5, 2));
System.out.println("\nComparator:");
List<String> names = new ArrayList<>(Arrays.asList("Charlie", "Alice", "Bob"));
System.out.println(" Before: " + names);
names.sort((a, b) -> a.compareTo(b));
System.out.println(" Sorted: " + names);
names.sort((a, b) -> b.compareTo(a));
System.out.println(" Reverse: " + names);
}
}
import java.util.*;
public class Basic {
public static void main(String[] args) {
System.out.println("No parameters:\n");
Runnable task = () -> System.out.println(" Hello from lambda!");
task.run();
Runnable oldWay = new Runnable() {
@Override
public void run() {
System.out.println(" Hello from anonymous class");
}
};
oldWay.run();
System.out.println("\nSingle parameter:");
interface Printer {
void print(String message);
}
Printer p1 = message -> System.out.println(" " + message);
p1.print("No parentheses");
Printer p2 = (message) -> System.out.println(" " + message);
p2.print("With parentheses");
System.out.println("\nMultiple parameters:");
interface Calculator {
int calculate(int a, int b);
}
Calculator add = (a, b) -> a + b;
Calculator subtract = (a, b) -> a - b;
Calculator multiply = (a, b) -> a * b;
int calcB = ;
System.out.println(" 5 + " + calcB + " = " + add.calculate(5, calcB));
System.out.println(" 5 - " + calcB + " = " + subtract.calculate(5, calcB));
System.out.println(" 5 * " + calcB + " = " + multiply.calculate(5, calcB));
System.out.println("\nBlock body:");
Calculator divide = (a, b) -> {
if (b == 0) {
System.out.println(" Error: Division by zero");
return 0;
}
return a / b;
};
System.out.println(" 10 / " + calcB + " = " + divide.calculate(10, calcB));
System.out.println("\nExplicit types:");
Calculator power = (int base, int exp) -> {
int result = 1;
for (int i = 0; i < exp; i++) {
result *= base;
}
return result;
};
System.out.println(" 2^3 = " + power.calculate(2, 3));
System.out.println(" 5^2 = " + power.calculate(5, 2));
System.out.println("\nComparator:");
List<String> names = new ArrayList<>(Arrays.asList("Charlie", "Alice", "Bob"));
System.out.println(" Before: " + names);
names.sort((a, b) -> a.compareTo(b));
System.out.println(" Sorted: " + names);
names.sort((a, b) -> b.compareTo(a));
System.out.println(" Reverse: " + names);
}
}
import java.util.*;
public class Basic {
public static void main(String[] args) {
System.out.println("No parameters:\n");
Runnable task = () -> System.out.println(" Hello from lambda!");
task.run();
Runnable oldWay = new Runnable() {
@Override
public void run() {
System.out.println(" Hello from anonymous class");
}
};
oldWay.run();
System.out.println("\nSingle parameter:");
interface Printer {
void print(String message);
}
Printer p1 = message -> System.out.println(" " + message);
p1.print("No parentheses");
Printer p2 = (message) -> System.out.println(" " + message);
p2.print("With parentheses");
System.out.println("\nMultiple parameters:");
interface Calculator {
int calculate(int a, int b);
}
Calculator add = (a, b) -> a + b;
Calculator subtract = (a, b) -> a - b;
Calculator multiply = (a, b) -> a * b;
int calcB = ;
System.out.println(" 5 + " + calcB + " = " + add.calculate(5, calcB));
System.out.println(" 5 - " + calcB + " = " + subtract.calculate(5, calcB));
System.out.println(" 5 * " + calcB + " = " + multiply.calculate(5, calcB));
System.out.println("\nBlock body:");
Calculator divide = (a, b) -> {
if (b == 0) {
System.out.println(" Error: Division by zero");
return 0;
}
return a / b;
};
System.out.println(" 10 / " + calcB + " = " + divide.calculate(10, calcB));
System.out.println("\nExplicit types:");
Calculator power = (int base, int exp) -> {
int result = 1;
for (int i = 0; i < exp; i++) {
result *= base;
}
return result;
};
System.out.println(" 2^3 = " + power.calculate(2, 3));
System.out.println(" 5^2 = " + power.calculate(5, 2));
System.out.println("\nComparator:");
List<String> names = new ArrayList<>(Arrays.asList("Charlie", "Alice", "Bob"));
System.out.println(" Before: " + names);
names.sort((a, b) -> a.compareTo(b));
System.out.println(" Sorted: " + names);
names.sort((a, b) -> b.compareTo(a));
System.out.println(" Reverse: " + names);
}
}
(params) -> expression - concise syntax for single-method interfaces.
Lambda parameters
Different ways to specify parameters.
import java.util.*;
import java.util.function.*;
public class Parameters {
public static void main(String[] args) {
System.out.println("Single parameter:\n");
UnaryOperator<Integer> square = x -> x * x;
UnaryOperator<Integer> doubler = x -> x * 2;
UnaryOperator<String> upper = s -> s.toUpperCase();
System.out.println(" square(5) = " + square.apply(5));
System.out.println(" doubler(7) = " + doubler.apply(7));
System.out.println(" upper('hello') = " + upper.apply("hello"));
System.out.println("\nTwo parameters:");
BinaryOperator<Integer> max = (a, b) -> a > b ? a : b;
BinaryOperator<Integer> min = (a, b) -> a < b ? a : b;
BinaryOperator<String> concat = (s1, s2) -> s1 + s2;
System.out.println(" max(10, 20) = " + max.apply(10, 20));
System.out.println(" min(10, 20) = " + min.apply(10, 20));
System.out.println(" concat('Hello', ' World') = " + concat.apply("Hello", " World"));
System.out.println("\nDifferent input/output types:");
BiFunction<String, Integer, String> repeat = (str, n) -> {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) {
sb.append(str);
}
return sb.toString();
};
BiFunction<Integer, Integer, Double> divide = (a, b) -> (double) a / b;
int repeatCount = ;
System.out.println(" repeat('ab', " + repeatCount + ") = " +
repeat.apply("ab", repeatCount));
System.out.println(" divide(10, 4) = " + divide.apply(10, 4));
System.out.println("\nBlock with parameters:");
BiFunction<Integer, Integer, String> compare = (a, b) -> {
if (a > b) {
return a + " is greater";
} else if (a < b) {
return b + " is greater";
} else {
return "Equal";
}
};
System.out.println(" compare(10, 5): " + compare.apply(10, 5));
System.out.println(" compare(3, 8): " + compare.apply(3, 8));
System.out.println(" compare(7, 7): " + compare.apply(7, 7));
System.out.println("\nList operations:");
List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
System.out.print(" Numbers: ");
numbers.forEach(n -> System.out.print(n + " "));
System.out.println();
numbers.removeIf(n -> n % 2 == 0);
System.out.println(" After removing evens: " + numbers);
System.out.println("\nCustom interface:");
interface Validator {
boolean validate(String input);
}
Validator notEmpty = s -> s != null && !s.isEmpty();
Validator isEmail = s -> s.contains("@");
Validator minLength = s -> s.length() >= 5;
String test1 = "user@example.com";
String test2 = "ab";
System.out.println(" '" + test1 + "' not empty: " + notEmpty.validate(test1));
System.out.println(" '" + test1 + "' is email: " + isEmail.validate(test1));
System.out.println(" '" + test2 + "' min length: " + minLength.validate(test2));
}
}
import java.util.*;
import java.util.function.*;
public class Parameters {
public static void main(String[] args) {
System.out.println("Single parameter:\n");
UnaryOperator<Integer> square = x -> x * x;
UnaryOperator<Integer> doubler = x -> x * 2;
UnaryOperator<String> upper = s -> s.toUpperCase();
System.out.println(" square(5) = " + square.apply(5));
System.out.println(" doubler(7) = " + doubler.apply(7));
System.out.println(" upper('hello') = " + upper.apply("hello"));
System.out.println("\nTwo parameters:");
BinaryOperator<Integer> max = (a, b) -> a > b ? a : b;
BinaryOperator<Integer> min = (a, b) -> a < b ? a : b;
BinaryOperator<String> concat = (s1, s2) -> s1 + s2;
System.out.println(" max(10, 20) = " + max.apply(10, 20));
System.out.println(" min(10, 20) = " + min.apply(10, 20));
System.out.println(" concat('Hello', ' World') = " + concat.apply("Hello", " World"));
System.out.println("\nDifferent input/output types:");
BiFunction<String, Integer, String> repeat = (str, n) -> {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) {
sb.append(str);
}
return sb.toString();
};
BiFunction<Integer, Integer, Double> divide = (a, b) -> (double) a / b;
int repeatCount = ;
System.out.println(" repeat('ab', " + repeatCount + ") = " +
repeat.apply("ab", repeatCount));
System.out.println(" divide(10, 4) = " + divide.apply(10, 4));
System.out.println("\nBlock with parameters:");
BiFunction<Integer, Integer, String> compare = (a, b) -> {
if (a > b) {
return a + " is greater";
} else if (a < b) {
return b + " is greater";
} else {
return "Equal";
}
};
System.out.println(" compare(10, 5): " + compare.apply(10, 5));
System.out.println(" compare(3, 8): " + compare.apply(3, 8));
System.out.println(" compare(7, 7): " + compare.apply(7, 7));
System.out.println("\nList operations:");
List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
System.out.print(" Numbers: ");
numbers.forEach(n -> System.out.print(n + " "));
System.out.println();
numbers.removeIf(n -> n % 2 == 0);
System.out.println(" After removing evens: " + numbers);
System.out.println("\nCustom interface:");
interface Validator {
boolean validate(String input);
}
Validator notEmpty = s -> s != null && !s.isEmpty();
Validator isEmail = s -> s.contains("@");
Validator minLength = s -> s.length() >= 5;
String test1 = "user@example.com";
String test2 = "ab";
System.out.println(" '" + test1 + "' not empty: " + notEmpty.validate(test1));
System.out.println(" '" + test1 + "' is email: " + isEmail.validate(test1));
System.out.println(" '" + test2 + "' min length: " + minLength.validate(test2));
}
}
import java.util.*;
import java.util.function.*;
public class Parameters {
public static void main(String[] args) {
System.out.println("Single parameter:\n");
UnaryOperator<Integer> square = x -> x * x;
UnaryOperator<Integer> doubler = x -> x * 2;
UnaryOperator<String> upper = s -> s.toUpperCase();
System.out.println(" square(5) = " + square.apply(5));
System.out.println(" doubler(7) = " + doubler.apply(7));
System.out.println(" upper('hello') = " + upper.apply("hello"));
System.out.println("\nTwo parameters:");
BinaryOperator<Integer> max = (a, b) -> a > b ? a : b;
BinaryOperator<Integer> min = (a, b) -> a < b ? a : b;
BinaryOperator<String> concat = (s1, s2) -> s1 + s2;
System.out.println(" max(10, 20) = " + max.apply(10, 20));
System.out.println(" min(10, 20) = " + min.apply(10, 20));
System.out.println(" concat('Hello', ' World') = " + concat.apply("Hello", " World"));
System.out.println("\nDifferent input/output types:");
BiFunction<String, Integer, String> repeat = (str, n) -> {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) {
sb.append(str);
}
return sb.toString();
};
BiFunction<Integer, Integer, Double> divide = (a, b) -> (double) a / b;
int repeatCount = ;
System.out.println(" repeat('ab', " + repeatCount + ") = " +
repeat.apply("ab", repeatCount));
System.out.println(" divide(10, 4) = " + divide.apply(10, 4));
System.out.println("\nBlock with parameters:");
BiFunction<Integer, Integer, String> compare = (a, b) -> {
if (a > b) {
return a + " is greater";
} else if (a < b) {
return b + " is greater";
} else {
return "Equal";
}
};
System.out.println(" compare(10, 5): " + compare.apply(10, 5));
System.out.println(" compare(3, 8): " + compare.apply(3, 8));
System.out.println(" compare(7, 7): " + compare.apply(7, 7));
System.out.println("\nList operations:");
List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
System.out.print(" Numbers: ");
numbers.forEach(n -> System.out.print(n + " "));
System.out.println();
numbers.removeIf(n -> n % 2 == 0);
System.out.println(" After removing evens: " + numbers);
System.out.println("\nCustom interface:");
interface Validator {
boolean validate(String input);
}
Validator notEmpty = s -> s != null && !s.isEmpty();
Validator isEmail = s -> s.contains("@");
Validator minLength = s -> s.length() >= 5;
String test1 = "user@example.com";
String test2 = "ab";
System.out.println(" '" + test1 + "' not empty: " + notEmpty.validate(test1));
System.out.println(" '" + test1 + "' is email: " + isEmail.validate(test1));
System.out.println(" '" + test2 + "' min length: " + minLength.validate(test2));
}
}
x -> x*2 (one param, no parens), (x, y) -> x+y (multiple), (int x) -> x*2 (typed).
Block lambda
Multiple statements in lambda body.
import java.util.*;
import java.util.function.*;
public class Block {
public static void main(String[] args) {
System.out.println("Single vs block:\n");
Function<Integer, Integer> single = x -> x * 2;
Function<Integer, Integer> block = x -> {
int result = x * 2;
return result;
};
System.out.println(" Single: " + single.apply(5));
System.out.println(" Block: " + block.apply(5));
System.out.println("\nComplex logic:");
Function<Integer, String> classify = n -> {
if (n < 0) {
return "negative";
} else if (n == 0) {
return "zero";
} else if (n % 2 == 0) {
return "positive even";
} else {
return "positive odd";
}
};
System.out.println(" classify(-5): " + classify.apply(-5));
System.out.println(" classify(0): " + classify.apply(0));
System.out.println(" classify(4): " + classify.apply(4));
System.out.println(" classify(7): " + classify.apply(7));
System.out.println("\nLocal variables:");
BiFunction<Integer, Integer, Integer> gcd = (a, b) -> {
int temp;
while (b != 0) {
temp = b;
b = a % b;
a = temp;
}
return a;
};
System.out.println(" gcd(48, 18) = " + gcd.apply(48, 18));
System.out.println(" gcd(100, 35) = " + gcd.apply(100, 35));
System.out.println("\nValidation:");
Function<String, Boolean> isValidPassword = password -> {
if (password == null || password.length() < 8) {
return false;
}
boolean hasDigit = false;
boolean hasLetter = false;
for (char c : password.toCharArray()) {
if (Character.isDigit(c)) hasDigit = true;
if (Character.isLetter(c)) hasLetter = true;
}
return hasDigit && hasLetter;
};
String passwordToCheck = ;
System.out.println(" '" + passwordToCheck + "' valid: " +
isValidPassword.apply(passwordToCheck));
System.out.println(" 'short' valid: " + isValidPassword.apply("short"));
System.out.println(" 'onlyletters' valid: " + isValidPassword.apply("onlyletters"));
System.out.println("\nMulti-step processing:");
Function<List<Integer>, Double> average = list -> {
if (list.isEmpty()) {
return 0.0;
}
int sum = 0;
for (int n : list) {
sum += n;
}
return (double) sum / list.size();
};
List<Integer> scores = Arrays.asList(85, 90, 78, 92, 88);
System.out.println(" Average score: " + average.apply(scores));
System.out.println("\nException handling:");
BiFunction<Integer, Integer, Integer> safeDivide = (a, b) -> {
try {
return a / b;
} catch (ArithmeticException e) {
System.out.println(" Error: " + e.getMessage());
return 0;
}
};
System.out.println(" 10 / 2 = " + safeDivide.apply(10, 2));
System.out.println(" 10 / 0 = " + safeDivide.apply(10, 0));
}
}
import java.util.*;
import java.util.function.*;
public class Block {
public static void main(String[] args) {
System.out.println("Single vs block:\n");
Function<Integer, Integer> single = x -> x * 2;
Function<Integer, Integer> block = x -> {
int result = x * 2;
return result;
};
System.out.println(" Single: " + single.apply(5));
System.out.println(" Block: " + block.apply(5));
System.out.println("\nComplex logic:");
Function<Integer, String> classify = n -> {
if (n < 0) {
return "negative";
} else if (n == 0) {
return "zero";
} else if (n % 2 == 0) {
return "positive even";
} else {
return "positive odd";
}
};
System.out.println(" classify(-5): " + classify.apply(-5));
System.out.println(" classify(0): " + classify.apply(0));
System.out.println(" classify(4): " + classify.apply(4));
System.out.println(" classify(7): " + classify.apply(7));
System.out.println("\nLocal variables:");
BiFunction<Integer, Integer, Integer> gcd = (a, b) -> {
int temp;
while (b != 0) {
temp = b;
b = a % b;
a = temp;
}
return a;
};
System.out.println(" gcd(48, 18) = " + gcd.apply(48, 18));
System.out.println(" gcd(100, 35) = " + gcd.apply(100, 35));
System.out.println("\nValidation:");
Function<String, Boolean> isValidPassword = password -> {
if (password == null || password.length() < 8) {
return false;
}
boolean hasDigit = false;
boolean hasLetter = false;
for (char c : password.toCharArray()) {
if (Character.isDigit(c)) hasDigit = true;
if (Character.isLetter(c)) hasLetter = true;
}
return hasDigit && hasLetter;
};
String passwordToCheck = ;
System.out.println(" '" + passwordToCheck + "' valid: " +
isValidPassword.apply(passwordToCheck));
System.out.println(" 'short' valid: " + isValidPassword.apply("short"));
System.out.println(" 'onlyletters' valid: " + isValidPassword.apply("onlyletters"));
System.out.println("\nMulti-step processing:");
Function<List<Integer>, Double> average = list -> {
if (list.isEmpty()) {
return 0.0;
}
int sum = 0;
for (int n : list) {
sum += n;
}
return (double) sum / list.size();
};
List<Integer> scores = Arrays.asList(85, 90, 78, 92, 88);
System.out.println(" Average score: " + average.apply(scores));
System.out.println("\nException handling:");
BiFunction<Integer, Integer, Integer> safeDivide = (a, b) -> {
try {
return a / b;
} catch (ArithmeticException e) {
System.out.println(" Error: " + e.getMessage());
return 0;
}
};
System.out.println(" 10 / 2 = " + safeDivide.apply(10, 2));
System.out.println(" 10 / 0 = " + safeDivide.apply(10, 0));
}
}
import java.util.*;
import java.util.function.*;
public class Block {
public static void main(String[] args) {
System.out.println("Single vs block:\n");
Function<Integer, Integer> single = x -> x * 2;
Function<Integer, Integer> block = x -> {
int result = x * 2;
return result;
};
System.out.println(" Single: " + single.apply(5));
System.out.println(" Block: " + block.apply(5));
System.out.println("\nComplex logic:");
Function<Integer, String> classify = n -> {
if (n < 0) {
return "negative";
} else if (n == 0) {
return "zero";
} else if (n % 2 == 0) {
return "positive even";
} else {
return "positive odd";
}
};
System.out.println(" classify(-5): " + classify.apply(-5));
System.out.println(" classify(0): " + classify.apply(0));
System.out.println(" classify(4): " + classify.apply(4));
System.out.println(" classify(7): " + classify.apply(7));
System.out.println("\nLocal variables:");
BiFunction<Integer, Integer, Integer> gcd = (a, b) -> {
int temp;
while (b != 0) {
temp = b;
b = a % b;
a = temp;
}
return a;
};
System.out.println(" gcd(48, 18) = " + gcd.apply(48, 18));
System.out.println(" gcd(100, 35) = " + gcd.apply(100, 35));
System.out.println("\nValidation:");
Function<String, Boolean> isValidPassword = password -> {
if (password == null || password.length() < 8) {
return false;
}
boolean hasDigit = false;
boolean hasLetter = false;
for (char c : password.toCharArray()) {
if (Character.isDigit(c)) hasDigit = true;
if (Character.isLetter(c)) hasLetter = true;
}
return hasDigit && hasLetter;
};
String passwordToCheck = ;
System.out.println(" '" + passwordToCheck + "' valid: " +
isValidPassword.apply(passwordToCheck));
System.out.println(" 'short' valid: " + isValidPassword.apply("short"));
System.out.println(" 'onlyletters' valid: " + isValidPassword.apply("onlyletters"));
System.out.println("\nMulti-step processing:");
Function<List<Integer>, Double> average = list -> {
if (list.isEmpty()) {
return 0.0;
}
int sum = 0;
for (int n : list) {
sum += n;
}
return (double) sum / list.size();
};
List<Integer> scores = Arrays.asList(85, 90, 78, 92, 88);
System.out.println(" Average score: " + average.apply(scores));
System.out.println("\nException handling:");
BiFunction<Integer, Integer, Integer> safeDivide = (a, b) -> {
try {
return a / b;
} catch (ArithmeticException e) {
System.out.println(" Error: " + e.getMessage());
return 0;
}
};
System.out.println(" 10 / 2 = " + safeDivide.apply(10, 2));
System.out.println(" 10 / 0 = " + safeDivide.apply(10, 0));
}
}
(x) -> { statements; return value; } - braces and return for complex logic.
Effectively final
Lambda can access local variables if effectively final.
import java.util.*;
import java.util.function.*;
public class EffectivelyFinal {
public static void main(String[] args) {
System.out.println("Effectively final:\n");
int multiplier = ;
Function<Integer, Integer> multiply = x -> x * multiplier;
System.out.println(" 5 * 10 = " + multiply.apply(5));
System.out.println(" 7 * 10 = " + multiply.apply(7));
System.out.println("\nMultiple captures:");
String prefix = "Value: ";
String suffix = "!";
Function<Integer, String> format = n -> prefix + n + suffix;
System.out.println(" " + format.apply(42));
System.out.println(" " + format.apply(99));
System.out.println("\nMethod parameters:");
processList(Arrays.asList(1, 2, 3, 4, 5), 3);
System.out.println("\nInstance variables:");
Counter counter = new Counter();
counter.demonstrate();
System.out.println("\nExplicit final:");
final int factor = 5;
BinaryOperator<Integer> scale = (a, b) -> (a + b) * factor;
System.out.println(" (2 + 3) * 5 = " + scale.apply(2, 3));
System.out.println("\nArray capture:");
int[] counters = {0}; // Effectively final reference, mutable content
Runnable increment = () -> counters[0]++;
increment.run();
increment.run();
increment.run();
System.out.println(" Counter: " + counters[0]);
}
static void processList(List<Integer> numbers, int threshold) {
numbers.forEach(n -> {
if (n > threshold) {
System.out.println(" " + n + " exceeds " + threshold);
}
});
}
}
class Counter {
private int count = 0;
void demonstrate() {
Runnable inc = () -> count++;
inc.run();
inc.run();
inc.run();
System.out.println(" Count: " + count);
Supplier<Integer> getCount = () -> this.count;
System.out.println(" Get count: " + getCount.get());
}
}
import java.util.*;
import java.util.function.*;
public class EffectivelyFinal {
public static void main(String[] args) {
System.out.println("Effectively final:\n");
int multiplier = ;
Function<Integer, Integer> multiply = x -> x * multiplier;
System.out.println(" 5 * 10 = " + multiply.apply(5));
System.out.println(" 7 * 10 = " + multiply.apply(7));
System.out.println("\nMultiple captures:");
String prefix = "Value: ";
String suffix = "!";
Function<Integer, String> format = n -> prefix + n + suffix;
System.out.println(" " + format.apply(42));
System.out.println(" " + format.apply(99));
System.out.println("\nMethod parameters:");
processList(Arrays.asList(1, 2, 3, 4, 5), 3);
System.out.println("\nInstance variables:");
Counter counter = new Counter();
counter.demonstrate();
System.out.println("\nExplicit final:");
final int factor = 5;
BinaryOperator<Integer> scale = (a, b) -> (a + b) * factor;
System.out.println(" (2 + 3) * 5 = " + scale.apply(2, 3));
System.out.println("\nArray capture:");
int[] counters = {0}; // Effectively final reference, mutable content
Runnable increment = () -> counters[0]++;
increment.run();
increment.run();
increment.run();
System.out.println(" Counter: " + counters[0]);
}
static void processList(List<Integer> numbers, int threshold) {
numbers.forEach(n -> {
if (n > threshold) {
System.out.println(" " + n + " exceeds " + threshold);
}
});
}
}
class Counter {
private int count = 0;
void demonstrate() {
Runnable inc = () -> count++;
inc.run();
inc.run();
inc.run();
System.out.println(" Count: " + count);
Supplier<Integer> getCount = () -> this.count;
System.out.println(" Get count: " + getCount.get());
}
}
import java.util.*;
import java.util.function.*;
public class EffectivelyFinal {
public static void main(String[] args) {
System.out.println("Effectively final:\n");
int multiplier = ;
Function<Integer, Integer> multiply = x -> x * multiplier;
System.out.println(" 5 * 10 = " + multiply.apply(5));
System.out.println(" 7 * 10 = " + multiply.apply(7));
System.out.println("\nMultiple captures:");
String prefix = "Value: ";
String suffix = "!";
Function<Integer, String> format = n -> prefix + n + suffix;
System.out.println(" " + format.apply(42));
System.out.println(" " + format.apply(99));
System.out.println("\nMethod parameters:");
processList(Arrays.asList(1, 2, 3, 4, 5), 3);
System.out.println("\nInstance variables:");
Counter counter = new Counter();
counter.demonstrate();
System.out.println("\nExplicit final:");
final int factor = 5;
BinaryOperator<Integer> scale = (a, b) -> (a + b) * factor;
System.out.println(" (2 + 3) * 5 = " + scale.apply(2, 3));
System.out.println("\nArray capture:");
int[] counters = {0}; // Effectively final reference, mutable content
Runnable increment = () -> counters[0]++;
increment.run();
increment.run();
increment.run();
System.out.println(" Counter: " + counters[0]);
}
static void processList(List<Integer> numbers, int threshold) {
numbers.forEach(n -> {
if (n > threshold) {
System.out.println(" " + n + " exceeds " + threshold);
}
});
}
}
class Counter {
private int count = 0;
void demonstrate() {
Runnable inc = () -> count++;
inc.run();
inc.run();
inc.run();
System.out.println(" Count: " + count);
Supplier<Integer> getCount = () -> this.count;
System.out.println(" Get count: " + getCount.get());
}
}
Variables accessed in lambda can't be modified. Effectively final = never reassigned.
Common use cases
Where lambdas shine.
import java.util.*;
import java.util.function.*;
public class UseCases {
public static void main(String[] args) {
System.out.println("Thread creation:\n");
Thread oldThread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(" Old way thread");
}
});
Thread newThread = new Thread(() -> {
System.out.println(" Lambda thread");
});
try {
oldThread.start();
oldThread.join();
newThread.start();
newThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("\nSorting:");
List<String> names = new ArrayList<>(
Arrays.asList("Charlie", "Alice", "Bob", "David"));
names.sort((a, b) -> a.compareTo(b));
System.out.println(" By name: " + names);
names.sort((a, b) -> Integer.compare(a.length(), b.length()));
System.out.println(" By length: " + names);
names.sort((a, b) -> {
char lastA = a.charAt(a.length() - 1);
char lastB = b.charAt(b.length() - 1);
return Character.compare(lastA, lastB);
});
System.out.println(" By last char: " + names);
System.out.println("\nList processing:");
List<Integer> numbers = new ArrayList<>(
Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
System.out.print(" All: ");
numbers.forEach(n -> System.out.print(n + " "));
System.out.println();
numbers.removeIf(n -> n % 2 == 0);
System.out.println(" After removing evens: " + numbers);
numbers.replaceAll(n -> n * 10);
System.out.println(" After * 10: " + numbers);
System.out.println("\nMap operations:");
Map<String, Integer> scores = new LinkedHashMap<>();
scores.put("Alice", 85);
scores.put("Bob", 92);
scores.put("Charlie", 78);
scores.forEach((name, score) ->
System.out.println(" " + name + ": " + score));
scores.replaceAll((name, score) -> score + 5); // Curve grades
System.out.println(" After curve: " + scores);
scores.computeIfAbsent("David", k -> 80);
System.out.println(" After adding David: " + scores);
System.out.println("\nCustom callbacks:");
processData(Arrays.asList(1, 2, 3, 4, 5),
n -> n * 2,
n -> System.out.println(" Processed: " + n)
);
System.out.println("\nEvent handlers:");
Button button = new Button("Click me");
button.setOnClick(() -> System.out.println(" Button clicked!"));
button.setOnClick(() -> System.out.println(" Action performed"));
button.click();
System.out.println("\nConditional logic:");
List<Integer> values = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
int cutoff = ;
filterAndPrint(values, n -> n > cutoff, "Greater than " + cutoff);
filterAndPrint(values, n -> n % 2 == 0, "Even numbers");
filterAndPrint(values, n -> n % 3 == 0, "Divisible by 3");
}
static void processData(List<Integer> data,
Function<Integer, Integer> processor,
Consumer<Integer> outputter) {
for (Integer item : data) {
Integer processed = processor.apply(item);
outputter.accept(processed);
}
}
static void filterAndPrint(List<Integer> list,
Predicate<Integer> filter,
String label) {
System.out.print(" " + label + ": ");
list.stream()
.filter(filter)
.forEach(n -> System.out.print(n + " "));
System.out.println();
}
}
class Button {
private String text;
private Runnable onClick;
Button(String text) {
this.text = text;
}
void setOnClick(Runnable action) {
this.onClick = action;
}
void click() {
if (onClick != null) {
onClick.run();
}
}
}
import java.util.*;
import java.util.function.*;
public class UseCases {
public static void main(String[] args) {
System.out.println("Thread creation:\n");
Thread oldThread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(" Old way thread");
}
});
Thread newThread = new Thread(() -> {
System.out.println(" Lambda thread");
});
try {
oldThread.start();
oldThread.join();
newThread.start();
newThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("\nSorting:");
List<String> names = new ArrayList<>(
Arrays.asList("Charlie", "Alice", "Bob", "David"));
names.sort((a, b) -> a.compareTo(b));
System.out.println(" By name: " + names);
names.sort((a, b) -> Integer.compare(a.length(), b.length()));
System.out.println(" By length: " + names);
names.sort((a, b) -> {
char lastA = a.charAt(a.length() - 1);
char lastB = b.charAt(b.length() - 1);
return Character.compare(lastA, lastB);
});
System.out.println(" By last char: " + names);
System.out.println("\nList processing:");
List<Integer> numbers = new ArrayList<>(
Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
System.out.print(" All: ");
numbers.forEach(n -> System.out.print(n + " "));
System.out.println();
numbers.removeIf(n -> n % 2 == 0);
System.out.println(" After removing evens: " + numbers);
numbers.replaceAll(n -> n * 10);
System.out.println(" After * 10: " + numbers);
System.out.println("\nMap operations:");
Map<String, Integer> scores = new LinkedHashMap<>();
scores.put("Alice", 85);
scores.put("Bob", 92);
scores.put("Charlie", 78);
scores.forEach((name, score) ->
System.out.println(" " + name + ": " + score));
scores.replaceAll((name, score) -> score + 5); // Curve grades
System.out.println(" After curve: " + scores);
scores.computeIfAbsent("David", k -> 80);
System.out.println(" After adding David: " + scores);
System.out.println("\nCustom callbacks:");
processData(Arrays.asList(1, 2, 3, 4, 5),
n -> n * 2,
n -> System.out.println(" Processed: " + n)
);
System.out.println("\nEvent handlers:");
Button button = new Button("Click me");
button.setOnClick(() -> System.out.println(" Button clicked!"));
button.setOnClick(() -> System.out.println(" Action performed"));
button.click();
System.out.println("\nConditional logic:");
List<Integer> values = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
int cutoff = ;
filterAndPrint(values, n -> n > cutoff, "Greater than " + cutoff);
filterAndPrint(values, n -> n % 2 == 0, "Even numbers");
filterAndPrint(values, n -> n % 3 == 0, "Divisible by 3");
}
static void processData(List<Integer> data,
Function<Integer, Integer> processor,
Consumer<Integer> outputter) {
for (Integer item : data) {
Integer processed = processor.apply(item);
outputter.accept(processed);
}
}
static void filterAndPrint(List<Integer> list,
Predicate<Integer> filter,
String label) {
System.out.print(" " + label + ": ");
list.stream()
.filter(filter)
.forEach(n -> System.out.print(n + " "));
System.out.println();
}
}
class Button {
private String text;
private Runnable onClick;
Button(String text) {
this.text = text;
}
void setOnClick(Runnable action) {
this.onClick = action;
}
void click() {
if (onClick != null) {
onClick.run();
}
}
}
import java.util.*;
import java.util.function.*;
public class UseCases {
public static void main(String[] args) {
System.out.println("Thread creation:\n");
Thread oldThread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(" Old way thread");
}
});
Thread newThread = new Thread(() -> {
System.out.println(" Lambda thread");
});
try {
oldThread.start();
oldThread.join();
newThread.start();
newThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("\nSorting:");
List<String> names = new ArrayList<>(
Arrays.asList("Charlie", "Alice", "Bob", "David"));
names.sort((a, b) -> a.compareTo(b));
System.out.println(" By name: " + names);
names.sort((a, b) -> Integer.compare(a.length(), b.length()));
System.out.println(" By length: " + names);
names.sort((a, b) -> {
char lastA = a.charAt(a.length() - 1);
char lastB = b.charAt(b.length() - 1);
return Character.compare(lastA, lastB);
});
System.out.println(" By last char: " + names);
System.out.println("\nList processing:");
List<Integer> numbers = new ArrayList<>(
Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
System.out.print(" All: ");
numbers.forEach(n -> System.out.print(n + " "));
System.out.println();
numbers.removeIf(n -> n % 2 == 0);
System.out.println(" After removing evens: " + numbers);
numbers.replaceAll(n -> n * 10);
System.out.println(" After * 10: " + numbers);
System.out.println("\nMap operations:");
Map<String, Integer> scores = new LinkedHashMap<>();
scores.put("Alice", 85);
scores.put("Bob", 92);
scores.put("Charlie", 78);
scores.forEach((name, score) ->
System.out.println(" " + name + ": " + score));
scores.replaceAll((name, score) -> score + 5); // Curve grades
System.out.println(" After curve: " + scores);
scores.computeIfAbsent("David", k -> 80);
System.out.println(" After adding David: " + scores);
System.out.println("\nCustom callbacks:");
processData(Arrays.asList(1, 2, 3, 4, 5),
n -> n * 2,
n -> System.out.println(" Processed: " + n)
);
System.out.println("\nEvent handlers:");
Button button = new Button("Click me");
button.setOnClick(() -> System.out.println(" Button clicked!"));
button.setOnClick(() -> System.out.println(" Action performed"));
button.click();
System.out.println("\nConditional logic:");
List<Integer> values = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
int cutoff = ;
filterAndPrint(values, n -> n > cutoff, "Greater than " + cutoff);
filterAndPrint(values, n -> n % 2 == 0, "Even numbers");
filterAndPrint(values, n -> n % 3 == 0, "Divisible by 3");
}
static void processData(List<Integer> data,
Function<Integer, Integer> processor,
Consumer<Integer> outputter) {
for (Integer item : data) {
Integer processed = processor.apply(item);
outputter.accept(processed);
}
}
static void filterAndPrint(List<Integer> list,
Predicate<Integer> filter,
String label) {
System.out.print(" " + label + ": ");
list.stream()
.filter(filter)
.forEach(n -> System.out.print(n + " "));
System.out.println();
}
}
class Button {
private String text;
private Runnable onClick;
Button(String text) {
this.text = text;
}
void setOnClick(Runnable action) {
this.onClick = action;
}
void click() {
if (onClick != null) {
onClick.run();
}
}
}
Collections, streams, event handlers, callbacks - anywhere functional interfaces are used.
Exercise: Practical.java
Refactor anonymous classes to lambdas