CÔNG NGHỆ THÔNG TIN >> BÀI VIẾT CHỌN LỌC

Lambda Expression và Functional Interface trong java 8

Đăng lúc: 09:11 AM - 21/12/2023 bởi Charles Chung - 311

Trong bài này tôi sẽ giới thiệu về biểu thức Lambda, Functional Interface trong java 8 và một số cách sử dụng Lambda expressions

Giới thiệu

Biểu thức Lambda là một tính năng mới được giới thiệu từ phiên bản Java 8 để thuận tiện lập trình chức năng (facilitate functional programming). Phong cách lập trình Functional Programming có một số ưu điểm như

  • Easy to Test Programs (dễ test chương trình)
  • Thread safe (an toàn khi sử dụng Luồng)
  • Modular (Module hóa)

Đặc điểm của Lambda expression

  • Một dạng biểu thức rút gọn
  • Loại bỏ việc khai báo phương thức mới tường minh
  • Một phương thức mong đợi và chấp nhận thông số đầu vào và trả kết quả đầu ra

Cú pháp

(parameters)-> {statements}

trong đó: parameters là tham số ( có thể không hoặc có một hoặc nhiều tham số), statements là các câu lệnh

Functional Interface: Java 8 gọi các Interface có duy nhất một method trừu tượng là các Functional Interface, nó cũng có thể được gọi là Single Abstract Method (SAM) một cụm từ đôi khi chúng ta bắt gặp. Java 8 cũng giới thiệu một annotation mới là @FunctionalInterface. Nó có thể sử dụng cho mục đích bắt lỗi ở thời điểm biên dịch nếu vô tình thêm một method trừu tượng khác nữa vào interface có đánh dấu bởi annotation này mà vi phạm quy tắc của Functional Interface. Lợi ích chính của functional interface là chúng ta có thể sử dụng Lambda Expression để tạo ra thể hiện (instance) cho interface đó.

Một số ví dụ

Ví dụ 1:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
* Khai báo interface
* Lưu ý: mỗi dạng biểu thức Lambda phải khai báo một interface
* và bên trong chỉ có duy nhất một phương thức
* để tránh người dùng khai báo nhiều phương thức trong giao diện
* bạn thêm annotaion @FunctionalInterface vào nhé
*/
@FunctionalInterface
interface Hanam88 {
	void welcome();
}
public class Program {
	public static void main(String[] args) {
		//Cách sử dụng lớp nặc danh (annonymous class) và thực thi phương thức của interface
		Hanam88 hh = new Hanam88() {
			@Override
			public void welcome() {
				System.out.println("Welcome to hanam88.com");
			}
		};
		hh.welcome();
		//Cách sử dụng biểu thức Lambda và thực thi phương thức của interface (rõ ràng code ngắn hơn)
		Hanam88 hh1 = () -> System.out.println("Welcome to hanam88.com");
		hh1.welcome();
	}
}

Kết luận: Qua ví dụ 1 chúng ta có thể thấy biểu thức Lambda là một cách viết gọn "phương thức của lớp nặc danh trong java" và code trong cặp ngoặc { } là code thực thi phương thức của interface

Ví dụ 2: 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/*
* Khai báo interface
*/
@FunctionalInterface
interface Calculation {
	int operation(int x, int y);
}
public class Program {
	public static void main(String[] args) {
		int a = 10, b = 2;
		//sử dụng biểu thức lambda để thực thi operation tính tổng 2 số
		Calculation cal1 = (x, y) -> {
			return x + y;
		}; // hoặc (x,y)->x+y;
		int tong = cal1.operation(a, b);
		System.out.printf("Tổng %d+%d=%d\n", a, b, tong);
		//sử dụng biểu thức lambda để thực thi operation tính tích 2 số
		Calculation cal2 = (x, y) -> {
			return x * y;
		};
		int tich = cal2.operation(a, b);
		System.out.printf("Tích %d+%d=%d\n", a, b, tich);
		//sử dụng biểu thức lambda để thực thi operation tính hiệu 2 số
		Calculation cal3 = (x, y) -> {
			return x - y;
		};
		int hieu = cal3.operation(a, b);
		System.out.printf("Hiệu %d+%d=%d\n", a, b, hieu);
		//sử dụng biểu thức lambda để thực thi operation tính thương 2 số
		Calculation cal4 = (x, y) -> {
			return x / y;
		};
		int thuong = cal4.operation(a, b);
		System.out.printf("Thương %d+%d=%d\n", a, b, thuong);
	}
}

Kết luận: Qua ví dụ 2 chúng ta có thể thấy cùng một phương thức trong interface nhưng mỗi khi sử dụng biểu thức Lambda chúng ta có thể triển khai code bên trong { } khác nhau. Biểu thức lambda có thể có một hoặc nhiều tham số.

Ví dụ 3: 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import java.util.Arrays;
import java.util.List;
public class Program {
	public static void main(String[] args) {
		//Khai báo một mảng chuỗi
		List<String> names = Arrays.asList("Dũng", "Vân", "Thanh", "Hải", "Linh", "Hà");
		//sử dụng biểu thức lambda trong phương thức forEach của chuỗi
		names.forEach(name -> System.out.println(name));
	}
}

 

Kết luận: Qua ví dụ 3 chúng ta có thể thấy biểu thức Lambda có thể sử dụng truyền vào tham số của phương thức khác khi tham số đó có kiểu Functional Interface.

Ví dụ 4:

 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
@FunctionalInterface
interface FunctionGeneric<T1, T2, R> {
	R operation(T1 p1, T2 p2);
}
public class Program {
	public static void main(String[] args) {
		//sử dụng Function Interafce với hai tham số đầu vào kiểu nguyên và đầu ra kiểu nguyên
		FunctionGeneric<Integer, Integer, Integer> f = (a, b) -> a / b;
		int div = f.operation(5, 2);
		System.out.println("Div: " + div);
		//sử dụng Function Interafce với hai tham số đầu vào kiểu nguyên và đầu ra kiểu double
		FunctionGeneric<Integer, Integer, Double> f1 = (a, b) -> (double) a / b;
		double div1 = f1.operation(5, 2);
		System.out.println("Div: " + div1);
	}
}

 

Kết luận: Qua ví dụ 4 chúng ta có thể tự định nghĩa FunctionalInterface sử dụng Generic để có thể dùng cho nhiều kiểu dữ liệu khác nhau

Trong Java cũng cung cấp sẵn một số Functional Interface

  • Function<T,R>: nhận 1 tham số đầu vào kiểu T và có trả về giá trị kiểu R, phương thức bên trong là apply.
  • Consumer<T>: nhận 1 tham số đầu vào kiểu T và không trả về giá trị, phương thức bên trong là accept
  • Predicate<T>: nhận 1 tham số đầu vào kiểu T và có trả về giá trị kiểu boolean, phương thức bên trong là test.

Mọi thắc mắc xin liên hệ thầy Charles Chung

thay lời cảm ơn!

QUẢNG CÁO - TIẾP THỊ