Đang tải...

Hiểu về Java Stream API – Viết code ngắn gọn và dễ đọc hơn

30/05/2026
7 phút đọc
Hiểu về Java Stream API – Viết code ngắn gọn và dễ đọc hơn
## Giới thiệu Khi làm việc với Java, chúng ta thường xuyên phải xử lý danh sách dữ liệu như: * Danh sách nhân viên * Danh sách đơn hàng * Danh sách sản phẩm * Kế...

Giới thiệu

Khi làm việc với Java, chúng ta thường xuyên phải xử lý danh sách dữ liệu như:

  • Danh sách nhân viên
  • Danh sách đơn hàng
  • Danh sách sản phẩm
  • Kết quả truy vấn từ database

Trước Java 8, các thao tác như lọc (filter), sắp xếp (sort), chuyển đổi dữ liệu (map) hay tính toán tổng hợp thường được thực hiện bằng các vòng lặp for truyền thống. Mặc dù hiệu quả, cách làm này đôi khi tạo ra nhiều đoạn code dài và khó đọc.

Để giải quyết vấn đề đó, Java 8 đã giới thiệu Stream API, cho phép lập trình viên xử lý tập dữ liệu theo phong cách khai báo (declarative programming) tương tự như SQL hoặc JavaScript Array Methods.

Stream API là gì?

Stream là một chuỗi các phần tử hỗ trợ thực hiện các phép toán trên dữ liệu theo dạng pipeline.

Thay vì mô tả từng bước xử lý dữ liệu bằng vòng lặp, lập trình viên chỉ cần mô tả kết quả mong muốn.

Ví dụ:

Giả sử có danh sách số:

List<Integer> numbers =
 Arrays.asList(1, 2, 3, 4, 5);

Muốn lấy các số chẵn:

List<Integer> evenNumbers =
 numbers.stream()
 .filter(n -> n % 2 == 0)
 .toList();

Kết quả:

[2, 4]

Code ngắn gọn và thể hiện rõ mục đích xử lý.

Tạo Stream

Có nhiều cách tạo Stream trong Java.

Từ Collection:

List<String> names =
 List.of("An", "Bình", "Cường");

Stream<String> stream =
 names.stream();

Từ mảng:

String[] names =
 {"An", "Bình", "Cường"};

Stream<String> stream =
 Arrays.stream(names);

Từ Stream.of():

Stream<String> stream =
 Stream.of("Java", "Spring", "Docker");

Sử dụng filter() để lọc dữ liệu

filter() là một trong những hàm được sử dụng nhiều nhất.

Ví dụ lấy nhân viên trên 30 tuổi:

List<Employee> employees =
 getEmployees();

List<Employee> result =
 employees.stream()
 .filter(emp -> emp.getAge() > 30)
 .toList();

Ưu điểm:

  • Code dễ đọc
  • Không cần tạo danh sách tạm
  • Tránh nhiều vòng lặp lồng nhau

Sử dụng map() để chuyển đổi dữ liệu

Trong thực tế, đôi khi chúng ta không cần toàn bộ object mà chỉ cần một số trường dữ liệu.

Ví dụ lấy danh sách tên nhân viên:

List<String> names =
 employees.stream()
 .map(Employee::getName)
 .toList();

Nếu dùng vòng lặp truyền thống:

List<String> names =
 new ArrayList<>();

for(Employee employee : employees){
 names.add(employee.getName());
}

Stream giúp code ngắn gọn và dễ hiểu hơn đáng kể.

Sử dụng sorted() để sắp xếp

Ví dụ sắp xếp lương giảm dần:

List<Employee> result =
 employees.stream()
 .sorted(
 Comparator.comparing(
 Employee::getSalary
 ).reversed()
 )
 .toList();

Kỹ thuật này thường được dùng trong:

  • Dashboard
  • Báo cáo
  • API trả về danh sách dữ liệu

Sử dụng collect() để tổng hợp dữ liệu

Một trong những sức mạnh lớn nhất của Stream API là khả năng tổng hợp dữ liệu.

Ví dụ nhóm nhân viên theo phòng ban:

Map<String, List<Employee>> result =
 employees.stream()
 .collect(
 Collectors.groupingBy(
 Employee::getDepartment
 )
 );

Kết quả:

IT -> [Employee1, Employee2]

HR -> [Employee3, Employee4]

Đây là thao tác rất phổ biến trong các hệ thống quản lý doanh nghiệp.

Tính toán với Stream

Ví dụ tính tổng:

int total =
 numbers.stream()
 .mapToInt(Integer::intValue)
 .sum();

Tìm giá trị lớn nhất:

Optional<Integer> max =
 numbers.stream()
 .max(Integer::compareTo);

Tính trung bình:

double average =
 numbers.stream()
 .mapToInt(Integer::intValue)
 .average()
 .orElse(0);

Các thao tác này giúp giảm đáng kể lượng code phải viết.

Stream Pipeline hoạt động như thế nào?

Một Stream thường gồm ba phần:

Nguồn dữ liệu

employees.stream()

Các thao tác trung gian

.filter(...)
.map(...)
.sorted(...)

Thao tác kết thúc

.toList()
.collect(...)
.count()
.sum()

Khi chưa có thao tác kết thúc, Stream sẽ chưa thực hiện xử lý dữ liệu.

Đây được gọi là Lazy Evaluation (đánh giá lười).

Cơ chế này giúp tối ưu hiệu năng và giảm các phép tính không cần thiết.

Khi nào không nên dùng Stream?

Mặc dù Stream rất mạnh, không phải lúc nào cũng là lựa chọn tốt nhất.

Ví dụ:

  • Logic xử lý quá phức tạp
  • Cần debug từng bước
  • Có nhiều điều kiện rẽ nhánh
  • Cần thao tác thay đổi trạng thái liên tục

Trong những trường hợp này, vòng lặp for truyền thống đôi khi lại dễ hiểu hơn.

Nguyên tắc quan trọng là ưu tiên khả năng đọc hiểu của code thay vì cố gắng sử dụng Stream ở mọi nơi.

Parallel Stream

Java còn hỗ trợ xử lý song song thông qua Parallel Stream.

Ví dụ:

employees.parallelStream()
 .filter(emp ->
 emp.getSalary() > 1000)
 .toList();

Parallel Stream tận dụng nhiều CPU Core để xử lý dữ liệu.

Tuy nhiên không phải lúc nào cũng nhanh hơn.

Đối với tập dữ liệu nhỏ, chi phí tạo luồng có thể còn lớn hơn lợi ích mang lại.

Vì vậy nên benchmark trước khi áp dụng trong môi trường thực tế.

Kết luận

Java Stream API là một trong những tính năng quan trọng nhất được giới thiệu từ Java 8. Nó giúp lập trình viên viết code ngắn gọn hơn, dễ đọc hơn và tập trung vào mục tiêu xử lý dữ liệu thay vì các chi tiết kỹ thuật của vòng lặp.

Các phương thức như filter(), map(), sorted()collect() xuất hiện rất thường xuyên trong các dự án Java hiện đại, đặc biệt là các ứng dụng sử dụng Spring Boot. Việc thành thạo Stream API không chỉ giúp tăng năng suất lập trình mà còn giúp mã nguồn trở nên chuyên nghiệp và dễ bảo trì hơn trong các dự án lớn.

📚 Nguồn: Viblo

Bình luận

0 bình luận

Email không hiển thị công khai.

Chưa có bình luận nào. Hãy là người đầu tiên bình luận.

Chia sẻ bài viết

Cần tư vấn?

Liên hệ với chúng tôi để được hỗ trợ

Liên hệ ngay

Bài viết liên quan

Proxy hoạt động ở tầng nào trong mô hình TCP/IP? HTTP Proxy Và SOCKS5 nằm ở đâu?
09/06/2026

Proxy hoạt động ở tầng nào trong mô hình TCP/IP? HTTP Proxy Và SOCKS5 nằm ở đâu?

Proxy hoạt động ở tầng nào? Sau khi đã đi qua các tầng mạng như Physical Layer, Data Link Layer, Internet Layer, Transport Layer và Application Layer, ta có thể nhìn Proxy rõ ...

Đọc thêm
Red Team RAG: Khi mỗi pipeline là một đường hầm tối – Phần 2: Đầu độc dòng chảy – Từ ingestion đến sụp đổ
09/06/2026

Red Team RAG: Khi mỗi pipeline là một đường hầm tối – Phần 2: Đầu độc dòng chảy – Từ ingestion đến sụp đổ

## Lời mở đầu: Bạn đã vào hầm. Bây giờ, hãy đầu độc dòng nước. Ở phần 1, chúng ta đã đứng trước **cửa hầm**, học cách đọc bản đồ pipeline RAG, v...

Đọc thêm
Vì sao giá trị truyền thống luôn được đặt lên hàng đầu
09/06/2026

Vì sao giá trị truyền thống luôn được đặt lên hàng đầu

Giá trị truyền thống không chỉ là yếu tố mang tính hoài niệm, mà còn đóng vai trò nền tảng trong việc định hình bản sắc và chiều sâu của một công trình ...

Đọc thêm

Bắt đầu dự án của bạn

Hãy để Flash Dev đồng hành cùng bạn

Liên hệ ngay