Skip to main content

Command Palette

Search for a command to run...

Bài 3: Lambda Expressions và Method References

Published
5 min readView as Markdown

Mục tiêu:

  • Giúp người đọc hiểu và sử dụng thành thạo lambda expressionsmethod references trong Java 8.

  • Giải thích cú pháp, cách sử dụng, và so sánh hiệu năng giữa lambda và method references.

  • Cung cấp ví dụ minh họa chi tiết để áp dụng vào thực tế.


Dàn ý chi tiết:

1. Lambda Expressions

Lambda expressions là một trong những tính năng quan trọng nhất của Java 8, giúp viết code ngắn gọn và dễ đọc hơn bằng cách thay thế các lớp vô danh (anonymous classes).

  1. Cú pháp cơ bản:

    • Cú pháp chung: (parameters) -> { body }.

    • Nếu chỉ có một tham số và một biểu thức đơn giản, có thể bỏ qua dấu ngoặc và dấu ngoặc nhọn:

        (a, b) -> a + b; // Trả về tổng của a và b
        x -> x * x;      // Trả về bình phương của x
        () -> System.out.println("Hello"); // Không có tham số
      
    • Ví dụ:

        Runnable r = () -> System.out.println("Hello, World!");
        r.run(); // In ra "Hello, World!"
      
  2. Ví dụ minh họa:

    • Sử dụng lambda với Comparator:

        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
        names.sort((s1, s2) -> s1.compareTo(s2));
        System.out.println(names); // [Alice, Bob, Charlie]
      
    • Sử dụng lambda với Predicate:

        Predicate<Integer> isEven = num -> num % 2 == 0;
        System.out.println(isEven.test(4)); // true
      
  3. Lợi ích của lambda:

    • Giảm boilerplate code.

    • Code dễ đọc và dễ bảo trì hơn.

    • Hỗ trợ lập trình hàm (functional programming).


2. Method References

Method references là một cách ngắn gọn để viết lambda expressions khi lambda chỉ gọi một phương thức đã có sẵn.

  1. Bốn dạng method references:

    • Tham chiếu đến phương thức tĩnh (static method):

        Function<String, Integer> parseInt = Integer::parseInt;
        System.out.println(parseInt.apply("123")); // 123
      
    • Tham chiếu đến phương thức của một đối tượng cụ thể (instance method):

        List<String> names = Arrays.asList("Alice", "Bob");
        names.forEach(System.out::println); // In từng phần tử
      
    • Tham chiếu đến phương thức của một đối tượng tùy ý (instance method của một lớp):

        Function<String, String> toUpperCase = String::toUpperCase;
        System.out.println(toUpperCase.apply("hello")); // HELLO
      
    • Tham chiếu đến constructor:

        Supplier<List<String>> listSupplier = ArrayList::new;
        List<String> list = listSupplier.get();
      
  2. Ví dụ minh họa:

    • Sử dụng method reference với Comparator:

        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
        names.sort(String::compareToIgnoreCase);
        System.out.println(names); // [Alice, Bob, Charlie]
      
    • Sử dụng method reference với Function:

        Function<String, Integer> stringLength = String::length;
        System.out.println(stringLength.apply("Java")); // 4
      
  3. Lợi ích của method references:

    • Code ngắn gọn hơn so với lambda.

    • Tái sử dụng các phương thức đã có sẵn.


3. So sánh lambda và method references

  1. Hiệu năng:

    • Cả lambda và method references đều có hiệu năng tương đương nhau vì chúng đều được biên dịch thành các lớp vô danh (anonymous classes) hoặc sử dụng invokedynamic.

    • Tuy nhiên, method references có thể tối ưu hơn trong một số trường hợp vì chúng tái sử dụng phương thức đã có sẵn.

  2. Cú pháp:

    • Lambda linh hoạt hơn vì có thể chứa nhiều dòng code và logic phức tạp.

    • Method references ngắn gọn hơn nhưng chỉ phù hợp khi lambda chỉ gọi một phương thức đã có sẵn.

  3. Khi nào sử dụng:

    • Lambda: Khi cần thực hiện logic phức tạp hoặc không có phương thức sẵn có để tham chiếu.

    • Method references: Khi chỉ cần gọi một phương thức đã có sẵn và muốn code ngắn gọn hơn.


Ví dụ tổng hợp

  1. Sử dụng lambda và method references trong Stream:

     List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
    
     // Sử dụng lambda
     names.stream()
          .filter(name -> name.length() > 3)
          .forEach(name -> System.out.println(name));
    
     // Sử dụng method references
     names.stream()
          .filter(name -> name.length() > 3)
          .forEach(System.out::println);
    
  2. Sử dụng constructor reference:

     Supplier<List<String>> listSupplier = ArrayList::new;
     List<String> list = listSupplier.get();
     list.add("Java");
     System.out.println(list); // [Java]
    

Tổng kết

  • Lambda expressions giúp viết code ngắn gọn và linh hoạt hơn, đặc biệt khi làm việc với Functional Interface.

  • Method references là cách ngắn gọn để tham chiếu đến các phương thức đã có sẵn, giúp code dễ đọc hơn.

  • Tùy vào tình huống cụ thể, bạn có thể chọn sử dụng lambda hoặc method references để tối ưu hóa code.


Bài tập thực hành

  1. Viết một lambda expression để sắp xếp một danh sách các số nguyên theo thứ tự giảm dần.

  2. Sử dụng method reference để in ra độ dài của từng chuỗi trong một danh sách.

  3. Viết một lambda expression để tạo một danh sách mới chứa bình phương của các số nguyên từ một danh sách cho trước.


Gợi ý đáp án

  1. Sắp xếp danh sách:

     List<Integer> numbers = Arrays.asList(5, 3, 1, 4, 2);
     numbers.sort((a, b) -> b.compareTo(a));
     System.out.println(numbers); // [5, 4, 3, 2, 1]
    
  2. In độ dài chuỗi:

     List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
     names.stream()
          .map(String::length)
          .forEach(System.out::println); // 5, 3, 7
    
  3. Tạo danh sách bình phương:

     List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
     List<Integer> squares = numbers.stream()
                                    .map(x -> x * x)
                                    .collect(Collectors.toList());
     System.out.println(squares); // [1, 4, 9, 16]
    

Kết luận

Bài viết này đã hướng dẫn chi tiết cách sử dụng lambda expressionsmethod references trong Java 8. Hiểu rõ cách kết hợp các tính năng này giúp bạn viết code ngắn gọn, dễ đọc và tận dụng tối đa sức mạnh của Functional Interface.

More from this blog

hoangkim

366 posts