menu

VanThuong.Com

Blog học lập trình Java và SEO miễn phí.

Java 8 - Tìm hiểu cách dùng Consumer

Posted by on
Trong bài viết này, chúng ta sẽ cùng nhau tìm hiểu Interface Consumer<T> được giới thiệu trong Java 8. Consumer functional interface được sử dụng như một chỉ định mục tiêu của Lambda Expression. accept(T t) là phương thức của interface này và nó chỉ nhận đầu vào là một đối số và không trả về kết quả.

java.util.function.Consumer interface còn cung cấp cho chúng ta một phương thức default khác là andThen(Consumer<? super T> after). Phương thức này sẽ trả về một Consumer gộp, nó sẽ thực hiện (perform) theo một trình tự. Điều đó có nghĩa rằng khi bạn có 1 Consumer là consumerA và gọi consumerA.andThen(consumerB) thì nó sẽ tiếp tục thực hiện consumerB sau khi đã thực hiện consumerA.
Java 8 - Tìm hiểu cách dùng Consumer

Minh họa cách sử dụng Consumer

Ví dụ đơn giản nhất bên dưới đây sẽ giúp bạn hình dung ra cách sử dụng Consumer

import java.util.function.Consumer;
/*
* Official blog: w w w . v a n t h u o n g . c o m
*/
public class Main {
  public static void main(String[] args) {
    Consumer<String> c = (str) -> System.out.println(str.toLowerCase());
    c.accept("VanThuong.Com");
  }
}
Đoạn code trên sẽ in ra màn hình chuỗi `vanthuong.com`

Truyền consumer như parameter vào phương thức

Như bạn đã biết, Functional Interface có thể sử dụng như chỉ định mục tiêu của Lambda Expresion và Method Reference. Dưới đây là ví dụ giúp bạn hình dung nó dễ dàng hơn.
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
/*
* Official blog: w w w . v a n t h u o n g . c o m
*/
public class Main {
  public static void main(String[] args) {
    List<Student> students = Arrays.asList(
        new Student("Hang", 3),
        new Student("Nga", 4));

    loopThroughStudents(students, student -> System.out.println(student.getName()));
    loopThroughStudents(students, student -> student.setGpa(student.getGpa() * 1.5));
    loopThroughStudents(students, System.out::println);
  }

  public static void loopThroughStudents(List<Student> students, Consumer<Student> consumer) {
    for (Student student : students) {
      consumer.accept(student);
    }
  }
}

class Student {
  public String name;
  public double gpa;

  Student(String name, double g) {
    this.name = name;
    this.gpa = g;
  }

  // Generate getters and setters here

  @Override
  public String toString() {
    return "Student [name=" + name + ", gpa=" + gpa + "]";
  }
}

Trong đoạn code trên bạn thấy rằng, tôi có 1 phương thức là loopThroughtStudents với 2 tham số đầu vào là List<Student> studentsConsumer<Student> consumer. Như vậy, tôi đang truyền consumer như một parameter vào phương thức này. Phần body code được tôi viết lại bằng lambda expression và method reference mỗi khi gọi phương thức loopThroughStudents.
- Ở lần gọi thứ nhất, tôi in ra màn hình tên của Student
- Ở lần gọi thứ hai, tôi đang gán lại GPA cho Student và điều đó hoàn toàn hợp lệ vì nó đang là Object Reference
- Ở lần gọi thứ ba, tôi in ra toàn bộ thông tin của Student bằng cách truyền một consumer ở dạng Method Reference
Như vậy là chúng ta vừa tìm hiểu xong cách để sử dụng Consumer interface. Hi vọng rằng bạn sẽ hiểu được ví dụ này để nắm được lý thuyết.

Cách dùng phương thức andThen

Chúng ta xem lại syntax của nó nhé
default Consumer<T> andThen(Consumer<? super T> after)
Như tôi đã đề cập ở trên nó sẽ trả về một Consumer gộp (composed consumer) thực hiện một theo một trình tự. Cùng xem ví dụ dưới đây để xem nó hoạt dộng như thế nào nhé.
import java.util.function.Consumer;
/*
* Official blog: w w w . v a n t h u o n g . c o m
*/
public class Main {
  public static void main(String[] args) {
    Consumer<String> consumerA = (str) -> System.out.println(str.toLowerCase());
    Consumer<String> consumerB = (str) -> System.out.println(str.toUpperCase());
    
    consumerA.andThen(consumerB).accept("VanThuong.Com");
  }
}
Đoạn code trên sẽ thực thi consumerA trước sau đó tiếp tục thực thi consumerB dựa trên đầu vào là chuỗi `VanThuong.Com`. Kết quả in ra màn hình là:
vanthuong.com
VANTHUONG.COM

Khá đơn giản phải không nào, vậy chúng ta có thể sử dụng để truyền nó như một parameter vào phương thức không? Cùng xem qua ví dụ bên dưới đây nhé.
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

/*
* Official blog: w w w . v a n t h u o n g . c o m
*/
public class Main {
  public static void main(String[] args) {
    List<Student> students = Arrays.asList(
        new Student("Hang", 3),
        new Student("Nga", 4));

    Consumer<Student> calculateGpa = student -> student.setGpa(student.getGpa() * 1.5);
    
    loopThroughStudents(students, student -> System.out.println(student.getName()));
    loopThroughStudents(students, calculateGpa.andThen(System.out::println));
  }

  public static void loopThroughStudents(List<Student> students, Consumer<Student> consumer) {
    for (Student student : students) {
      consumer.accept(student);
    }
  }
}

class Student {
  public String name;
  public double gpa;

  Student(String name, double g) {
    this.name = name;
    this.gpa = g;
  }

  // Generate getters and setters here
 
  @Override
  public String toString() {
    return "Student [name=" + name + ", gpa=" + gpa + "]";
  }
}
Như đoạn code trên đã mô tả, tôi tạo ra một consumer với tên là calculateGpa. Tôi truyền vào phương thức loopThroughStudents consumer gộp của nó là calculateGpa.andThen(System.out::println). Như vậy chúng ta hoàn toàn có thể truyền như một paramater.
Đoạn code trên sẽ in ra màn hình kết quả như sau:
Hang
Nga
Student [name=Hang, gpa=4.5]
Student [name=Nga, gpa=6.0]

Lời kết

Trong bài viết này chúng ta đã cùng nhau tìm hiểu qua Consumer interface được định nghĩa trong Java 8 và lợi ích của nó là gì. Ngoài ra, chúng ta cũng đã thực hành một vài ví dụ để biết được cách sử dụng phương thức accept() và andThen(). Với những ví dụ đơn giản này, tôi hi vọng rằng các bạn sẽ hiểu được chúng ở mức độ có thể. Bởi vì bạn cũng biết rằng, Tiếng Việt khó có thể diễn đạt dược trọn vẹn ý nghĩa của Tiếng Anh chuyên ngành.

Tóm lại, Consumer là một functional interface thực sự hữu ích để chúng ta sử dụng cho những phép toán không trả về kết quả. Nó mang lại cho chúng ta nhiều lợi ích khi có thể truyền như một parameter vào phương thức. Và thường thì chúng ta sẽ sử dụng consumer trong các trường hợp Object Reference. Chúc các bạn học tốt nhé.
Đăng bình luận

menu