Chào mừng đến với Diễn đàn lập trình - Cộng đồng lập trình.
Kết quả 1 đến 4 của 4
  1. #1
    Ngày tham gia
    Sep 2015
    Bài viết
    0

    [Java 8 - Lambda Expression] Tìm hiểu về Lambda Expression trong Java 8

    Chào tất cả anh chị em CViet, lâu lắm mềnh với quay trở lại và vẫn ăn hại như xưa [IMG]images/smilies/2.gif[/IMG]. Nhân dịp sau một năm làm một "doc-er" một "excel pro" quyết định "ủ mưu" cắp đit quay về nghề coder, người ta có nói không có gì hạnh phúc hơn được làm công việc mà mình yêu thích. Khởi động bằng một bài chia sẻ về những hiểu biết một "new feature" trong Java 8 đó là biểu thức Lambda. Mong anh chị em đọc vào góp ý [IMG]images/smilies/biggrin.png[/IMG]

    Java 8 đã được Oracle ra mắt vào ngày 25/3/2014 với rất nhiều cải tiến. Trong đó đáng chú ý là Java đã chính thức hỗ trợ biểu thức Lambda. Nếu bạn nào đã từng làm việc với C# chắc quá hiểu về biểu thức này rồi nhỉ.

    Trước khi vào bài chúng ta hãy xem một ví dụ một danh sách các số nguyên như sau

    Mã:
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
    Vậy thì làm thế nào để duyệt và in ra toàn bộ các số nguyên có trong list? Chắc chắn chúng ta sẽ làm thế này

    Mã:
    for (Integer numer : numbers) {       System.out.println(numer);}
    Việc làm này là quá quen thuộc và lặp đi lặp lại một cách rất nhàm chán nhiều lần trong quá trình phát triển các ứng dụng Java.

    Mô tả vào đời thực nó sẽ giống thế này:
    Một ngày cuối tuần đẹp trời bạn quyết định vào bếp phụ vợ nấu ăn và hãy xem xét cuộc đối thoại sau đây
    40pxBạn thấy đoạn hội thoại trên thế nào? Còn tôi thấy nó thật thừa thãi, giống như một đoạn code rác vậy.

    Đoạn hội thoại trên có thể "fix" lại như sau:
    - Vợ: Anh yêu! Lấy dùm em hết đồ ăn trong tủ lạnh ra nhá:
    - Chồng: Ok, honey!
    Wow một đoạn ... code tuyệt phải không =))

    Và Java 8 cũng cung cấp cho bạn một biểu thức tuyệt vời để giải quyết trường hợp như trên.
    Hãy xem lại đoạn code bên trên và thử áp biểu thức Lambda coi
    Một biểu thức Lambda sẽ có hai phần một phần là tham số phần kia là hành vi cần thực hiện và được cách nhau bởi một dấu ->

    Mã:
    numbers.forEach(value -> System.out.println(value));
    Ở đây cúng ta thấy biến value là một tham số còn System.out.println(value) là một hành vi (in dãy số)
    Chúng ta có thể để ý value không cần khai báo kiểu dữ liệu mà bộ biên dịch vẫn có thể hiểu được. Lợi hai chưa?

    Hoặc ta cũng có thể dùng toán tử :: để thực hiện việc này

    Mã:
    numbers.forEach(System.out::println);
    OK! nhìn đoạn code đã trở nên "ngon" và chuyên nghiệp hơn hơn rất nhiều phải không?
    Trước khi đọc tiếp bạn hay thử download bộ JDK 8 và Netbean IDE 8.0 để chạy thử coi.


    Chúng ta hãy tìm hiểu thêm cái gọi là "hành vi" mà tôi đã đề cập bên trên nhé.
    Hãy xét một ví dụ sau:
    Ta cần một phương thức để thực hiện tính tổng các số nguyên trong một List?
    Rất đơn giản là thực hiện một hàm như sau:

    Mã:
        public int sumAll(List<Integer> numbers) {        int total = 0;        for (int number : numbers) {            total += number;        }        return total;    }
    Vậy cần thêm hai hàm để thực hiện cộng các số lẻ và các số chẵn ???
    Code thêm hai hàm như sau nữa ???

    Mã:
        public int sumAllOdd(List<Integer> numbers) {        int total = 0;        for (int number : numbers) {            if (number % 2 != 0) {                total += number;            }        }        return total;    }    public int sumAllEven(List<Integer> numbers) {        int total = 0;        for (int number : numbers) {            if (number % 2 == 0) {                total += number;            }        }        return total;    }
    Ba hàm trên giống hệt nhau khác nhau mỗi biểu thức điều kiện.
    He he chắc bạn cũng đang nghĩ giống tôi hãy thử biểu thức Lambda cho vấn đề này xem

    Mã:
        public static int sumAllLambda(List<Integer> numbers, Predicate<Integer> p) {        int total = 0;        for (int number : numbers) {            if (p.test(number)) {                total += number;            }        }        return total;    }        public static boolean isPrime() {        return true;    }
    Trước khi giải thích hãy thử áp dụng trong hàm main coi
    Gọi hàm để tổng tất cả các số trong list

    Mã:
    sumAllLambda(numbers, n -> true)
    ở đây numebers là list các số nguyên
    n là tham số, true là hành vi và hành vi này luôn đúng cho nên hàm test của interface Predicate là luôn pass.
    Ta có thể thay true bằng các hành vi như kiểm tra số chẵn như sau

    Mã:
    sumAllLambda(numbers, n -> n % 2 == 0)
    hoặc kiểm tra số lẻ

    Mã:
    sumAllLambda(numbers, n -> n % 2 != 0)
    hoặc các số lớn hơn 3

    Mã:
    sumAllLambda(numbers, n -> n > 3 == 0)
    hoặc thậm chí ta cũng có thể viết một hàm kiểm tra số nguyên tố "isPrime" rồi truyền vào hành vi của biểu thức Lambda đều được.

    Mã:
    sumAllLambda(numbers, n -> isPrime(n))
    Ở đây bạn sẽ thắc mắc với mình là interface Predicate là gì? Trong Java 8 chúng ta có những functional interface hỗ trợ cho việc viết biểu thức Lambda
    Trước tiên tôi sẽ giới thiệu về Predicate, Consumer.
    Predicate thường dùng để xác định và kiểm tra một đối tượng theo một số tiêu chí
    Predicate cung cấp cho chúng ta 5 method sau đây (nguồn Java doc)

    Mã:
        //Returns a predicate which evaluates to true only if this predicate     //and the provided predicate both evaluate to true.    and(Predicate<? super T> p)     //Returns a predicate which negates the result of this predicate.    negate()     //Returns a predicate which evaluates to true if either     //this predicate or the provided predicate evaluates to true    or(Predicate<? super T> p)     //Returns true if the input object matches some criteria    test(T t)     //Returns a predicate that evaluates to true if both or neither     //of the component predicates evaluate to true    xor(Predicate<? super T> p)
    Consumer thường được sử dụng để chấp nhận một đối tượng để thực hiện một hành vi nào đấy, consumer cung cấp cho chúng ta 1 method là

    Mã:
        /**     * Performs this operation on the given argument.     *     * @param t the input argument     */    void accept(T t);
    Đọc có vẻ khó hiểu phết nhờ, ví dụ cái nhá.
    Ta xét một bài toán sau: Viết một chương chính bán vé, nếu trẻ em dưới 6 tuổi sẽ được giảm giá 50%
    Ta sẽ khai báo một lớp khách hàng đơn giản như đan rổ như sau:

    Mã:
        public static class Customer {        int age = 0;        float price = 0;        float discount = 0;        public Customer(int age, int price, int discount) {            this.age = age;            this.price = price;            this.discount = discount;        }                public void printTicketPrice() {            float newPrice = price - discount;            System.out.println("Ticket price: " + newPrice);        }    }
    Ta viết thêm một method sử lý tính tiền vé như sau

    Mã:
        public static Customer updateTicketPrice(Customer customer,            Predicate<Customer> predicate,            Consumer<Customer> consumer) {         //Ở đây ta xử dụng method test của Predicate để kiểm tra dữ liệu đầu vào.        if (predicate.test(customer)) {            //Ở đây ta dùng method accept của Consumer để discount giá vé.            consumer.accept(customer);        }        return customer;    }
    Ta viết một hàm main rồi áp dụng biểu thức Lambda như sau xem

    Mã:
            int ticketPrice = 50000;        Customer customer1 = new Customer(27, ticketPrice, 0);        customer1 = updateTicketPrice(customer1,                                         //Lambda expression for Predicate interface                                        customer -> customer.age <= 6,                                         //Lambda expression for Consumer interface                                        customer -> customer.discount = ticketPrice/2);        customer1.printTicketPrice();                Customer customer2 = new Customer(6, ticketPrice, 0);        customer2 = updateTicketPrice(customer2,                                         //Lambda expression for Predicate interface                                        customer -> customer.age <= 6,                                         //Lambda expression for Consumer interface                                        customer -> customer.discount = ticketPrice/2);        customer2.printTicketPrice();                Chạy thử và in ra màn hình bạn sẽ thấy hai kết quả sau:
    Mã:
            Ticket price: 50000.0
            Ticket price: 25000.0
    Vậy ta có thể thấy customer2 là một đứa trẻ 6 tuổi và nó được giảm giá 50%

    (Còn tiếp)

  2. #2
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    cảm ơn vì bài viết [IMG]images/smilies/smile.png[/IMG]

  3. #3
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    bài viết quá hay mà lại bị drop

  4. #4
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    work like a charm [IMG]images/smilies/2.gif[/IMG]

 

 

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •