Vòng lặp for trong Java giúp bạn lặp lại một đoạn code theo số lần biết trước. Nó cũng duyệt được từng phần tử của mảng và collection. Đây là cấu trúc lặp phổ biến nhất, nên nắm chắc nó sẽ giúp bạn viết code gọn và ít lỗi hơn. Chúng tôi chia bài thành ba dạng: for thường, for-each và for có nhãn.
Cú pháp for thường

For thường có ba phần ngăn cách bằng dấu chấm phẩy: khởi tạo, điều kiện và bước nhảy.
for (int i = 0; i < 5; i++) {
System.out.println("Lần " + i);
}
Luồng chạy diễn ra như sau. Biến i được khởi tạo một lần. Java kiểm tra điều kiện; nếu đúng thì chạy thân vòng lặp, rồi thực hiện i++ và kiểm tra lại. Khi điều kiện sai, vòng lặp kết thúc.
Lỗi phổ biến nhất là lệch một đơn vị (off-by-one). Viết i <= 5 thay vì i < 5 sẽ chạy thêm một vòng. Với mảng thì nó gây ra ArrayIndexOutOfBoundsException. Hãy nhớ mảng n phần tử có chỉ số từ 0 đến n-1.
For-each để duyệt mảng và collection

Khi chỉ cần đọc từng phần tử và không quan tâm chỉ số, for-each ngắn gọn hơn nhiều.
int[] diem = {7, 8, 9};
int tong = 0;
for (int d : diem) {
tong += d;
}
System.out.println(tong); // 24
For-each dùng được với mảng và mọi đối tượng cài đặt Iterable, như các danh sách trong collections trong Java. Hạn chế của nó là bạn không biết chỉ số hiện tại. Bạn cũng không nên thêm hoặc xóa phần tử của collection trong lúc duyệt. Nếu làm vậy, Java sẽ ném ConcurrentModificationException.
List<String> ten = new ArrayList<>(List.of("An", "Binh", "Chi"));
for (String t : ten) {
if (t.equals("Binh")) {
ten.remove(t); // gây ConcurrentModificationException
}
}
Muốn xóa trong lúc duyệt, hãy dùng Iterator hoặc phương thức removeIf.
Vòng lặp lồng nhau và for có nhãn

Bạn có thể đặt vòng for bên trong vòng for khác. Ví dụ, in bảng cửu chương hoặc duyệt mảng hai chiều.
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
System.out.print(i * j + "\t");
}
System.out.println();
}
Lệnh break thông thường chỉ thoát vòng lặp trong cùng. Muốn thoát cả vòng ngoài, bạn gắn nhãn cho vòng ngoài và gọi break kèm nhãn.
tim:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (i * j == 4) {
System.out.println("Thấy ở " + i + "," + j);
break tim;
}
}
}
Nhãn dùng được với cả continue, khi đó Java nhảy sang lượt kế tiếp của vòng có nhãn. Tuy nhiên đừng lạm dụng. Nếu bạn cần quá nhiều nhãn, có lẽ nên tách đoạn code thành một phương thức riêng.
Những cách viết dễ mắc lỗi

- Đặt dấu chấm phẩy ngay sau ngoặc
for (...), khiến thân vòng lặp bị coi là rỗng. - Thay đổi biến đếm bên trong thân vòng lặp làm khó đoán số lần lặp.
- Dùng điều kiện luôn đúng như
for (;;)mà quên lệnhbreak, dẫn tới vòng lặp vô hạn.
Nếu vòng lặp có thể gặp dữ liệu hỏng, ví dụ chuyển chuỗi thành số, hãy bọc phần xử lý bằng try-catch. Bài xử lý ngoại lệ trong Java mô tả cách làm này. Phần cú pháp chính thức bạn có thể đối chiếu ở tutorial for của Oracle.
For và các lựa chọn thay thế
Không phải lúc nào for cũng là công cụ tốt nhất. Khi không biết trước số lần lặp, như lúc đọc đến hết dữ liệu, vòng while diễn đạt rõ hơn. Khi cần chạy thân vòng lặp ít nhất một lần, do-while là lựa chọn phù hợp.
Với collection, Java 8 mang tới forEach kết hợp biểu thức lambda và Stream. Chúng ngắn gọn cho các phép biến đổi đơn giản. Với logic phức tạp có nhiều nhánh, for truyền thống thường dễ đọc và dễ gỡ lỗi hơn.
List<String> ten = List.of("An", "Binh", "Chi");
ten.forEach(t -> System.out.println(t));
for (int i = 0; i < ten.size(); i++) {
System.out.println((i + 1) + ". " + ten.get(i));
}
Đoạn đầu gọn hơn, nhưng đoạn sau cho phép bạn dùng chỉ số để đánh số thứ tự. Mỗi cách có chỗ dùng riêng, và việc của bạn là chọn cách làm cho người đọc hiểu nhanh nhất.
Hiệu năng và thói quen tốt
Với danh sách, đừng gọi phương thức tốn kém trong điều kiện của vòng for nếu kết quả không đổi. Ví dụ i < danhSach.size() thì ổn vì size() rất rẻ. Nhưng nếu gọi phương thức truy vấn cơ sở dữ liệu ở đó, mỗi vòng lặp đều phải trả giá.
Khi duyệt LinkedList bằng chỉ số, mỗi lần gọi get(i) phải đi từ đầu danh sách. Vì vậy tổng thời gian tăng theo bình phương số phần tử. Dùng for-each trong trường hợp này sẽ nhanh hơn rõ rệt. Hiểu cấu trúc dữ liệu bên dưới sẽ ảnh hưởng tới cách viết vòng lặp.
Cuối cùng, hãy đặt tên biến đếm có nghĩa khi vòng lặp lồng nhau. Dùng hang và cot thay cho i và j giúp bạn khỏi nhầm khi duyệt ma trận. Nhất là khi trở lại đọc code sau vài tuần. Với những ai mới học, bài constructor trong Java cũng là bước tiếp theo hợp lý.
Hỏi đáp nhanh
Có thể khai báo nhiều biến trong cùng một vòng for không? Có, bạn ngăn cách bằng dấu phẩy. Ví dụ for (int i = 0, j = 10; i < j; i++, j--). Cách này tiện khi duyệt từ hai đầu vào giữa, như kiểm tra chuỗi đối xứng.
Biến đếm của for có dùng được sau vòng lặp không? Nếu khai báo trong phần khởi tạo thì không, vì phạm vi của nó chỉ nằm trong vòng for. Muốn dùng sau đó, hãy khai báo biến trước vòng lặp.
Bài tập nhỏ cho bạn: in các số chẵn từ 1 đến 50, rồi đổi sang tính tổng. Làm xong, thử viết lại bằng for-each trên một mảng để thấy khi nào mỗi kiểu thích hợp hơn.



