0

[Java Backend Zero to Hello] [Phase 2] BÀI 2.2: LAMBDA EXPRESSION

📚 Series: Java Backend Zero to Hello 📂 Phân đoạn: Phase 2: Java Core nâng cao 📖 Nội dung: BÀI 2.2: LAMBDA EXPRESSION 💡 Khóa học lập trình Backend Java & Spring Boot chuẩn doanh nghiệp từ con số 0.


BÀI 2.2: LAMBDA EXPRESSION

Mục tiêu

  • Hiểu Functional Interface
  • Viết Lambda Expression
  • Sử dụng Method Reference
  • Áp dụng vào Collection và Stream

1. FUNCTIONAL INTERFACE

Interface chỉ có đúng 1 abstract method (có thể có default/static).

@FunctionalInterface
public interface Calculator {
    int calculate(int a, int b);
}

Các Functional Interface phổ biến trong java.util.function

Interface Method Mô tả
Runnable void run() Không tham số, không trả về
Supplier<T> T get() Không tham số, trả về T
Consumer<T> void accept(T t) Có tham số, không trả về
Function<T,R> R apply(T t) T → R
BiFunction<T,U,R> R apply(T t, U u) (T, U) → R
Predicate<T> boolean test(T t) T → boolean
BiPredicate<T,U> boolean test(T t, U u) (T, U) → boolean
UnaryOperator<T> T apply(T t) T → T
BinaryOperator<T> T apply(T t, T u) (T, T) → T

2. LAMBDA EXPRESSION

Lambda là cách viết ngắn gọn cho implementation của Functional Interface.

2.1 Cú pháp

(parameters) -> { body }

2.2 Ví dụ cơ bản

// Không tham số
Runnable r1 = () -> System.out.println("Hello");
r1.run();

// 1 tham số
Consumer<String> c1 = (s) -> System.out.println(s);
Consumer<String> c2 = s -> System.out.println(s);  // Bỏ ngoặc đơn

// Nhiều tham số
Comparator<Integer> cmp = (a, b) -> Integer.compare(a, b);

// Body đơn giản - không cần return và {}
Function<Integer, Integer> square = x -> x * x;

// Body phức tạp - cần {} và return
Function<Integer, Integer> factorial = n -> {
    int result = 1;
    for (int i = 2; i <= n; i++) {
        result *= i;
    }
    return result;
};

2.3 So sánh với Anonymous Class

// Anonymous class - dài dòng
Runnable r1 = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello");
    }
};

// Lambda - ngắn gọn
Runnable r2 = () -> System.out.println("Hello");

3. METHOD REFERENCE

Cú pháp ngắn hơn nữa khi lambda chỉ gọi một method có sẵn.

3.1 Các loại Method Reference

Loại Cú pháp Ví dụ
Static method Class::staticMethod Math::max
Instance method (object cụ thể) instance::method System.out::println
Instance method (kiểu) Class::instanceMethod String::length
Constructor Class::new ArrayList::new

3.2 Ví dụ

// Static method
Function<Integer, Integer> abs = Math::abs;
abs.apply(-5);  // 5

// Instance method - object cụ thể
Consumer<String> printer = System.out::println;
printer.accept("Hello");

// Instance method - kiểu
Function<String, Integer> length = String::length;
length.apply("Hello");  // 5

// Constructor
Supplier<ArrayList<String>> listSupplier = ArrayList::new;
ArrayList<String> list = listSupplier.get();

3.3 So sánh Lambda vs Method Reference

// Lambda
Function<String, Integer> len1 = s -> s.length();

// Method Reference
Function<String, Integer> len2 = String::length;

4. SỬ DỤNG VỚI COLLECTION

4.1 forEach

List<String> names = Arrays.asList("An", "Bình", "Châu");

// forEach + Lambda
names.forEach(name -> System.out.println(name));

// forEach + Method Reference
names.forEach(System.out::println);

4.2 sort với Comparator

List<String> names = Arrays.asList("Châu", "An", "Bình");

// Lambda
names.sort((a, b) -> a.compareTo(b));

// Method Reference
names.sort(String::compareTo);

4.3 removeIf

List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6));
numbers.removeIf(n -> n % 2 == 0);  // [1, 3, 5]

5. SỬ DỤNG VỚI MAP

Map<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);

// forEach
map.forEach((k, v) -> System.out.println(k + " = " + v));

// compute
map.compute("A", (k, v) -> v == null ? 0 : v * 2);  // A = 2

// merge
map.merge("A", 10, Integer::sum);  // A = 12

// replaceAll
map.replaceAll((k, v) -> v * 10);  // A=20, B=20, C=30

6. CUSTOM FUNCTIONAL INTERFACE

@FunctionalInterface
public interface Validator<T> {
    boolean validate(T value);

    default Validator<T> and(Validator<T> other) {
        return value -> this.validate(value) && other.validate(value);
    }

    default Validator<T> or(Validator<T> other) {
        return value -> this.validate(value) || other.validate(value);
    }
}

// Sử dụng
Validator<String> notNull = s -> s != null;
Validator<String> notEmpty = s -> !s.isEmpty();
Validator<String> validator = notNull.and(notEmpty);

boolean valid = validator.validate("Hello");  // true

7. VARIABLE CAPTURE

Lambda có thể truy cập biến bên ngoài nhưng phải là effectively final.

int multiplier = 3;
Function<Integer, Integer> multiply = n -> n * multiplier;  // OK

// multiplier = 5;  // ❌ Lambda đã capture multiplier, không thể thay đổi

8. BÀI TẬP THỰC HÀNH

Bài 1: Sử dụng các Functional Interface

// Supplier - tạo UUID
Supplier<String> uuidSupplier = () -> UUID.randomUUID().toString();
String id = uuidSupplier.get();

// Consumer - in thông tin
Consumer<User> printUser = user -> System.out.println(user.getName());

// Function - chuyển User thành String
Function<User, String> getName = User::getName;

// Predicate - kiểm tra
Predicate<Integer> isEven = n -> n % 2 == 0;

Bài 2: Sort danh sách

List<User> users = getUsers();
users.sort(Comparator.comparing(User::getName));
users.sort(Comparator.comparingInt(User::getAge).reversed());

Bài 3: Filter và Transform

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

List<Integer> evenSquares = numbers.stream()
    .filter(n -> n % 2 == 0)
    .map(n -> n * n)
    .collect(Collectors.toList());
// [4, 16, 36, 64, 100]

Bài 4: Custom Validator

Tạo Validator<User> kiểm tra email hợp lệ, tuổi >= 18.


9. TÓM TẮT

Khái niệm Cú pháp Mục đích
Functional Interface Interface 1 abstract method Nền tảng cho Lambda
Lambda (params) -> body Viết ngắn gọn implementation
Method Reference Class::method Ngắn hơn Lambda
Consumer void accept(T) Xử lý, không trả về
Supplier T get() Cung cấp giá trị
Function R apply(T) Biến đổi
Predicate boolean test(T) Kiểm tra điều kiện

Bài tiếp theo: 2.3 Stream API


🧭 Điều hướng bài học

⭐ Hãy bookmark (clip) lại series để tiện theo dõi các bài học tiếp theo nhé!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí