Các Tính năng Hiện đại của Java 8 (Lambda, Stream API)
Chào mừng bạn quay trở lại series "Chinh Phục Java"! Trong suốt các bài học vừa qua, chúng ta đã tìm hiểu Java theo phong cách lập trình hướng đối tượng truyền thống. Tuy nhiên, kể từ phiên bản 8, Java đã có một cuộc "cách mạng". Nó giới thiệu các tính năng lấy cảm hứng từ lập trình hàm (functional programming). Những tính năng này giúp code của bạn trở nên **ngắn gọn, dễ đọc và mạnh mẽ hơn** một cách đáng kinh ngạc.
Hôm nay, chúng ta sẽ khám phá ba trong số những thay đổi quan trọng và hữu ích nhất của Java 8. Đó là **Biểu thức Lambda (Lambda Expressions)**, **Stream API**, và **Optional**. Việc nắm vững chúng sẽ thực sự nâng tầm kỹ năng lập trình Java của bạn.
1. Biểu thức Lambda (Lambda Expressions) - Viết code ngắn hơn
Trước Java 8, nếu bạn muốn truyền một "hành động" vào một phương thức, bạn thường phải tạo một lớp nặc danh (anonymous class). Code của bạn sẽ trông khá dài dòng. **Biểu thức Lambda** là một cách viết cực kỳ ngắn gọn cho các lớp nặc danh chỉ có một phương thức. Nó cho phép bạn biểu diễn một hàm như một khối code độc lập.
Cú pháp cơ bản của Lambda là `(tham_số) -> { thân_hàm }`. Nó loại bỏ tất cả các chi tiết thừa như tên phương thức, kiểu trả về. Hãy xem ví dụ về việc sắp xếp một danh sách. Trước đây và bây giờ, sự khác biệt là rất lớn.
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class LambdaExample {
public static void main(String[] args) {
List names = Arrays.asList("Bình", "An", "Cường", "Dũng");
// Cách cũ (trước Java 8): Dùng lớp nặc danh
// Collections.sort(names, new Comparator() {
// @Override
// public int compare(String a, String b) {
// return a.compareTo(b);
// }
// });
// Cách mới với Lambda: Ngắn gọn và dễ đọc hơn rất nhiều
Collections.sort(names, (String a, String b) -> a.compareTo(b));
// Thậm chí còn có thể ngắn hơn nữa
// Collections.sort(names, (a, b) -> a.compareTo(b));
System.out.println("Danh sách đã sắp xếp: " + names);
}
}
Lambda giúp bạn tập trung vào "cái gì" cần làm (so sánh `a` và `b`) thay vì "như thế nào" (tạo một lớp `Comparator`...).
2. Stream API - Xử lý Collection theo một cách mới
Đây có lẽ là tính năng thay đổi cuộc chơi lớn nhất của Java 8. **Stream API** cung cấp một cách hoàn toàn mới để xử lý các tập hợp dữ liệu (như List, Set). Thay vì dùng các vòng lặp `for` truyền thống, bạn sẽ tạo ra một "luồng" (stream) dữ liệu. Sau đó, bạn áp dụng một chuỗi các thao tác lên luồng đó.
Cách tiếp cận này được gọi là **khai báo (declarative)**. Bạn chỉ cần mô tả kết quả mình muốn. Java sẽ tự lo phần còn lại. Nó giúp code trở nên dễ đọc, dễ hiểu và có thể tận dụng các bộ xử lý đa lõi để chạy song song, tăng hiệu năng.
Các thao tác phổ biến trên Stream:
filter(): Lọc ra các phần tử thỏa mãn một điều kiện.map(): Biến đổi mỗi phần tử thành một dạng khác.collect(): Thu thập kết quả cuối cùng vào một Collection mới.
Hãy xem ví dụ: Tìm tất cả các sinh viên có điểm > 8 và lấy ra tên của họ.
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
// Giả sử có lớp Student với các thuộc tính name và score
// ...
public class StreamApiExample {
public static void main(String[] args) {
List students = new ArrayList<>();
students.add(new Student("An", 9.5));
students.add(new Student("Bình", 7.0));
students.add(new Student("Cường", 8.5));
// Sử dụng Stream API
List excellentStudentNames = students.stream() // 1. Tạo stream
.filter(student -> student.getScore() > 8.0) // 2. Lọc sinh viên điểm cao
.map(student -> student.getName()) // 3. Lấy tên của họ
.collect(Collectors.toList()); // 4. Thu thập kết quả
System.out.println("Tên các sinh viên xuất sắc: " + excellentStudentNames);
// Kết quả: [An, Cường]
}
}
Bạn có thể thấy, code với Stream API đọc lên gần giống như một câu văn mô tả yêu cầu, rất tự nhiên và dễ hiểu.
3. `Optional`: Xử lý giá trị `null` một cách an toàn
Lỗi `NullPointerException` (NPE) có lẽ là lỗi phổ biến và đáng sợ nhất trong Java. Nó xảy ra khi bạn cố gắng sử dụng một biến có giá trị là `null`. Java 8 giới thiệu lớp Optional để giải quyết vấn đề này. `Optional` là một lớp "container" hay "vỏ bọc". Nó có thể chứa một giá trị không-null, hoặc không chứa gì cả (empty).
Thay vì một phương thức trả về `null` khi không tìm thấy kết quả, giờ đây nó có thể trả về một `Optional` rỗng. Điều này **bắt buộc** người lập trình phải kiểm tra xem giá trị có tồn tại hay không trước khi sử dụng. Nó giúp loại bỏ hoàn toàn nguy cơ xảy ra `NullPointerException`.
import java.util.Optional;
public class OptionalExample {
// Phương thức này có thể trả về một giá trị hoặc không
public static Optional findUserById(int id) {
if (id == 1) {
return Optional.of("User An");
}
return Optional.empty(); // Trả về Optional rỗng thay vì null
}
public static void main(String[] args) {
Optional user1 = findUserById(1);
Optional user2 = findUserById(2);
// Cách xử lý an toàn
user1.ifPresent(name -> System.out.println("Tìm thấy: " + name));
// Cung cấp một giá trị mặc định nếu không tìm thấy
String userName2 = user2.orElse("Người dùng không tồn tại");
System.out.println(userName2);
}
}
Kết luận
Bạn vừa được trang bị những công cụ mạnh mẽ và hiện đại nhất của Java. Biểu thức Lambda giúp code ngắn gọn, Stream API thay đổi cách bạn xử lý dữ liệu, và Optional giúp bạn viết code an toàn hơn. Hãy bắt đầu áp dụng chúng vào các dự án của mình. Bạn sẽ thấy việc lập trình Java trở nên thú vị và hiệu quả hơn rất nhiều. Ở bài tiếp theo, chúng ta sẽ tìm hiểu về Lập trình Đa luồng.
0 Bình luận
Vui lòng đăng nhập để gửi bình luận.