+2

Vòng lặp trong Java (phần 2)

Giới thiệu

Vòng lặp "for" là một trong những cấu trúc lặp phổ biến và quan trọng trong ngôn ngữ lập trình Java. Nó cho phép bạn lặp lại một chuỗi các câu lệnh với một số lần lặp xác định hoặc lặp qua các phần tử trong một tập hợp (ví dụ: mảng) một cách hiệu quả. Vòng lặp "for" giúp rút ngắn code, làm cho code trở nên dễ đọc hơn và giảm sự lặp lại.

Vòng lặp for trong Java

Cấu trúc cơ bản

Cấu trúc cơ bản của vòng lặp "for" trong Java như sau:

for (khởi tạo; điều kiện; cập nhật) {
    // code thực thi trong vòng lặp
}
  • khởi tạo: Đây là một phần của code được thực hiện một lần duy nhất khi vòng lặp bắt đầu. Thường được sử dụng để khởi tạo biến đếm hoặc thiết lập giá trị ban đầu.

  • điều kiện: Điều kiện kiểm tra trước mỗi lần lặp. Nếu điều kiện là "true", vòng lặp tiếp tục thực hiện. Nếu điều kiện trở thành "false," vòng lặp kết thúc.

  • cập nhật: Đây là một phần của code được thực hiện sau mỗi lần lặp. Thường được sử dụng để cập nhật giá trị của biến đếm hoặc điều kiện để tiến tới điều kiện dừng.

Vòng lặp "for" là một công cụ mạnh mẽ để duyệt qua mảng hoặc tập hợp các phần tử, thực hiện các thao tác lặp lại một số lần cố định hoặc xây dựng các trình điều khiển cho các thuật toán phức tạp. Bằng cách hiểu cấu trúc và cách hoạt động của vòng lặp "for," bạn có thể viết code hiệu quả và dễ đọc hơn trong Java.

Một số trường hợp đặc biệt

Khi bạn thiếu một hoặc vài thành phần quan trọng trong vòng lặp "for" trong Java, ví dụ như không có phần khởi tạo, không có phần điều kiện, hoặc không có phần cập nhật, bạn sẽ gặp phải lỗi biên dịch hoặc code sẽ không hoạt động như mong muốn. Dưới đây là ví dụ về các tình huống khi các thành phần bị thiếu:

1. Thiếu phần khởi tạo:

public class MissingForInitialization {
    public static void main(String[] args) {
        int i = 0;
        for (; i < 5; i++) {
            System.out.println("Số: " + i);
        }
    }
}

Trong ví dụ này, phần khởi tạo của vòng lặp đã bị thiếu. Mặc dù việc này vẫn biên dịch và hoạt động, nó không làm cho code dễ đọc. Thông thường, bạn nên đặt phần khởi tạo trước dấu ;.

2. Thiếu phần điều kiện:

public class MissingForCondition {
    public static void main(String[] args) {
        for (int i = 0;; i++) {
            if (i >= 5) {
                break;
            }
            System.out.println("Số: " + i);
        }
    }
}

Trong ví dụ này, phần điều kiện của vòng lặp đã bị thiếu. Chương trình hoạt động, nhưng lúc này, điều kiện kiểm tra đã được đặt bên trong câu lệnh if. Tuy nhiên, điều này làm cho code trở nên khó đọc và hiểu hơn.

3. Thiếu phần cập nhật:

public class MissingForUpdate {
    public static void main(String[] args) {
        for (int i = 0; i < 5;) {
            System.out.println("Số: " + i);
            i++;
        }
    }
}

Trong ví dụ này, phần cập nhật của vòng lặp đã bị thiếu. code vẫn hoạt động, nhưng việc cập nhật biến i đã phải thực hiện bên ngoài vòng lặp, làm cho code trở nên khó đọc hơn. Thông thường, bạn nên đặt phần cập nhật bên trong vòng lặp.

Trong mọi trường hợp, tốt nhất là tuân thủ cấu trúc cơ bản của vòng lặp "for" bao gồm phần khởi tạo, điều kiện và cập nhật để làm cho code dễ đọc và dễ hiểu.

Ví dụ

Ví dụ 1

Dưới đây là một ví dụ đơn giản về việc sử dụng vòng lặp "for" để in ra các số từ 1 đến 5 trong ngôn ngữ lập trình Java:

public class VongLapForExample {
    public static void main(String[] args) {
        for (int i = 1; i <= 5; i++) {
            System.out.println("Số: " + i);
        }
    }
}

Trong ví dụ này:

  • Ta sử dụng vòng lặp "for" để khởi tạo biến i với giá trị ban đầu là 1 (int i = 1).
  • Điều kiện kiểm tra (i <= 5) đảm bảo rằng vòng lặp sẽ tiếp tục cho đến khi i không còn nhỏ hơn hoặc bằng 5.
  • Code bên trong vòng lặp đơn giản là in ra giá trị của i và sau đó tăng giá trị của i lên mỗi lần lặp (i++).
  • Kết quả của chương trình sẽ là in ra các số từ 1 đến 5 trên màn hình:
Số: 1
Số: 2
Số: 3
Số: 4
Số: 5

Ví dụ này minh họa cách sử dụng vòng lặp "for" để thực hiện một chuỗi các câu lệnh lặp lại một số lần cố định.

Ví dụ 2

Dưới đây là một ví dụ về cách sử dụng vòng lặp "for" trong một ứng dụng thực tế để duyệt qua danh sách các học viên và hiển thị thông tin của họ:

import java.util.ArrayList;

public class StudentManagementApp {
    public static void main(String[] args) {
        // Tạo một danh sách chứa thông tin của các học viên
        ArrayList<Student> students = new ArrayList<Student>();

        // Thêm các học viên vào danh sách
        students.add(new Student("Nguyễn Văn A", 25, "Hà Nội"));
        students.add(new Student("Trần Thị B", 22, "Hồ Chí Minh"));
        students.add(new Student("Lê Văn C", 23, "Đà Nẵng"));

        // Sử dụng vòng lặp "for" để duyệt qua danh sách và hiển thị thông tin của từng học viên
        for (int i = 0; i < students.size(); i++) {
            Student student = students.get(i);
            System.out.println("Học viên " + (i + 1) + ":");
            System.out.println("Tên: " + student.getName());
            System.out.println("Tuổi: " + student.getAge());
            System.out.println("Địa chỉ: " + student.getAddress());
            System.out.println();
        }
    }
}

class Student {
    private String name;
    private int age;
    private String address;

    public Student(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getAddress() {
        return address;
    }
}

Trong ví dụ này:

  • Ta định nghĩa một lớp Student để lưu trữ thông tin của học viên, bao gồm tên, tuổi và địa chỉ.

  • Tạo một danh sách students để lưu trữ thông tin của các học viên và thêm một số học viên vào danh sách.

  • Sử dụng vòng lặp "for" để duyệt qua danh sách students bằng cách sử dụng biến i làm chỉ mục. Vòng lặp này cho phép lặp qua từng học viên trong danh sách.

  • Trong mỗi lần lặp, ta lấy thông tin của học viên tại vị trí i bằng cách sử dụng students.get(i) và hiển thị thông tin của học viên bao gồm tên, tuổi và địa chỉ.

Kết quả của chương trình sẽ là:

Học viên 1:
Tên: Nguyễn Văn A
Tuổi: 25
Địa chỉ: Hà Nội

Học viên 2:
Tên: Trần Thị B
Tuổi: 22
Địa chỉ: Hồ Chí Minh

Học viên 3:
Tên: Lê Văn C
Tuổi: 23
Địa chỉ: Đà Nẵng

Ví dụ này minh họa cách sử dụng vòng lặp "for" để duyệt qua danh sách các học viên và thực hiện một hành động trên từng phần tử trong danh sách, trong trường hợp này là hiển thị thông tin của học viên.

Ví dụ 3

Vòng lặp "for" thường được sử dụng trong thuật toán tìm đường đi ngắn nhất, như thuật toán Dijkstra, để duyệt qua các đỉnh của đồ thị và cập nhật khoảng cách ngắn nhất từ đỉnh nguồn đến tất cả các đỉnh khác. Dưới đây là một ví dụ đơn giản về cách sử dụng vòng lặp "for" trong thuật toán Dijkstra:

import java.util.ArrayList;
import java.util.PriorityQueue;

public class DijkstraShortestPath {
    private int V; // Số lượng đỉnh
    private ArrayList<Edge>[] adj; // Danh sách kề

    public DijkstraShortestPath(int vertices) {
        this.V = vertices;
        adj = new ArrayList[V];
        for (int i = 0; i < V; i++) {
            adj[i] = new ArrayList<>();
        }
    }

    public void addEdge(int source, int destination, int weight) {
        Edge edge = new Edge(source, destination, weight);
        adj[source].add(edge);
    }

    public void shortestPath(int source) {
        int[] distance = new int[V];
        for (int i = 0; i < V; i++) {
            distance[i] = Integer.MAX_VALUE;
        }
        distance[source] = 0;

        PriorityQueue<Node> queue = new PriorityQueue<>();
        queue.add(new Node(source, 0));

        while (!queue.isEmpty()) {
            int u = queue.poll().vertex;

            for (Edge e : adj[u]) {
                int v = e.destination;
                int weight = e.weight;

                if (distance[u] != Integer.MAX_VALUE && distance[u] + weight < distance[v]) {
                    distance[v] = distance[u] + weight;
                    queue.add(new Node(v, distance[v]));
                }
            }
        }

        System.out.println("Khoảng cách ngắn nhất từ đỉnh " + source + " đến tất cả các đỉnh:");
        for (int i = 0; i < V; i++) {
            System.out.println("Đỉnh " + source + " đến Đỉnh " + i + ": " + distance[i]);
        }
    }

    public static void main(String[] args) {
        int vertices = 5;
        DijkstraShortestPath graph = new DijkstraShortestPath(vertices);

        graph.addEdge(0, 1, 2);
        graph.addEdge(0, 2, 4);
        graph.addEdge(1, 2, 1);
        graph.addEdge(1, 3, 7);
        graph.addEdge(2, 4, 3);
        graph.addEdge(3, 4, 2);

        int sourceVertex = 0;
        graph.shortestPath(sourceVertex);
    }

    class Edge {
        int source;
        int destination;
        int weight;

        public Edge(int source, int destination, int weight) {
            this.source = source;
            this.destination = destination;
            this.weight = weight;
        }
    }

    class Node implements Comparable<Node> {
        int vertex;
        int weight;

        public Node(int vertex, int weight) {
            this.vertex = vertex;
            this.weight = weight;
        }

        @Override
        public int compareTo(Node other) {
            return Integer.compare(this.weight, other.weight);
        }
    }
}

Trong ví dụ này, ta sử dụng vòng lặp "for" để duyệt qua các đỉnh của đồ thị và cập nhật khoảng cách ngắn nhất từ đỉnh nguồn (được chọn là đỉnh 0) đến tất cả các đỉnh khác trong đồ thị bằng thuật toán Dijkstra.

Vòng lặp "for" được sử dụng để duyệt qua tất cả các đỉnh của đồ thị (for (int i = 0; i < V; i++)). Trong mỗi lần lặp, ta kiểm tra và cập nhật khoảng cách từ đỉnh nguồn đến các đỉnh kề (for (Edge e : adj[u])). Nếu khoảng cách hiện tại từ đỉnh nguồn đến một đỉnh kề ngắn hơn khoảng cách hiện tại, ta cập nhật khoảng cách này.

Kết quả của chương trình sẽ là khoảng cách ngắn nhất từ đỉnh nguồn đến tất cả các đỉnh trong đồ thị.

Ví dụ 4

Dưới đây là code sử dụng vòng lặp "for" để triển khai thuật toán Kadane, một thuật toán dùng để tìm dãy con liên tiếp có tổng lớn nhất trong một mảng:

public class KadaneAlgorithm {
    public static int findMaxSubarraySum(int[] nums) {
        int maxSum = Integer.MIN_VALUE; // Khởi tạo tổng lớn nhất là giá trị âm vô cùng
        int currentSum = 0;

        for (int i = 0; i < nums.length; i++) {
            currentSum += nums[i];

            if (currentSum < nums[i]) {
                currentSum = nums[i];
            }

            if (currentSum > maxSum) {
                maxSum = currentSum;
            }
        }

        return maxSum;
    }

    public static void main(String[] args) {
        int[] array = {-2, 1, -3, 4, -1, 2, 1, -5, 4};
        int maxSum = findMaxSubarraySum(array);

        System.out.println("Tổng lớn nhất của dãy con liên tiếp là: " + maxSum);
    }
}

Trong đoạn code trên:

  • Ta sử dụng biến maxSum để theo dõi tổng lớn nhất của dãy con liên tiếp mà ta đã tìm thấy. Ban đầu, khởi tạo maxSum là giá trị âm vô cùng (Integer.MIN_VALUE) để đảm bảo rằng bất kỳ giá trị dương nào trong mảng sẽ lớn hơn nó.

  • Biến currentSum được sử dụng để tính tổng của dãy con hiện tại. Ta duyệt qua từng phần tử trong mảng bằng vòng lặp "for". Ở mỗi bước, ta cập nhật currentSum bằng cách thêm giá trị của phần tử nums[i].

  • Trong mỗi bước lặp, ta kiểm tra xem currentSum có nhỏ hơn giá trị nums[i] hay không. Nếu có, điều này có nghĩa rằng ta bắt đầu dãy con mới từ nums[i].

  • Sau đó, ta kiểm tra xem currentSum có lớn hơn maxSum hay không. Nếu có, ta cập nhật maxSum bằng currentSum.

  • Sau khi duyệt qua toàn bộ mảng, maxSum sẽ chứa tổng lớn nhất của dãy con liên tiếp, và ta trả về giá trị này.

Với mảng đầu vào trong ví dụ này, kết quả sẽ là 6 (4 - 1 + 2 + 1), là tổng lớn nhất của dãy con liên tiếp.

Một số lưu ý

Khi sử dụng vòng lặp "for" trong Java, dưới đây là một số lưu ý quan trọng giúp bạn viết code hiệu quả và tránh các lỗi phổ biến:

  1. Khởi tạo và cập nhật đúng: Đảm bảo rằng bạn đã khởi tạo biến đếm (counter) và cập nhật nó một cách đúng trong vòng lặp "for". Một lỗi khá phổ biến là quên khởi tạo biến hoặc quên cập nhật biến, dẫn đến vòng lặp không bao giờ kết thúc hoặc không thực hiện.

    for (int i = 0; i < 10; i++) {
        // code thực thi trong vòng lặp
    }
    
  2. Điều kiện dừng đúng: Xác định điều kiện dừng của vòng lặp "for" sao cho nó đúng khi bạn muốn vòng lặp kết thúc. Thường thì điều kiện được kiểm tra trước khi mỗi vòng lặp bắt đầu, vì vậy nếu điều kiện không đúng từ đầu, vòng lặp sẽ không thực hiện.

    for (int i = 0; i < 10; i++) {
        // code thực thi trong vòng lặp
    }
    
  3. Không Thay Đổi Biến Điều Kiện: Tránh thay đổi biến đếm bên trong vòng lặp một cách không cần thiết. Nếu bạn cần một biến để theo dõi số lần lặp, hãy sử dụng một biến khác thay vì thay đổi biến điều kiện.

    int total = 0;
    for (int i = 0; i < 10; i++) {
        total += i; // Hãy tránh thay đổi biến i ở đây
    }
    
  4. Kiểm Tra Mảng hoặc Danh Sách: Khi bạn sử dụng vòng lặp "for" để duyệt qua mảng hoặc danh sách, đảm bảo rằng bạn không vượt quá giới hạn của mảng hoặc danh sách để tránh lỗi truy cập ngoài phạm vi (ArrayIndexOutOfBoundsException hoặc IndexOutOfBoundsException).

    int[] numbers = {1, 2, 3, 4, 5};
    for (int i = 0; i < numbers.length; i++) {
        // code thực thi trong vòng lặp
    }
    
  5. Optimize Vòng Lặp: Trong một số trường hợp, bạn có thể cân nhắc tối ưu hóa vòng lặp, ví dụ, di chuyển biểu thức tính toán ra khỏi vòng lặp nếu nó không thay đổi trong quá trình lặp.

    int total = 0;
    int n = 10;
    for (int i = 1; i <= n; i++) {
        total += i;
    }
    
  6. Đặt Tên Biến Rõ Ràng: Sử dụng tên biến rõ ràng để làm cho code dễ đọc hơn và tránh gây hiểu nhầm về mục đích của biến đếm.

    for (int count = 0; count < 10; count++) {
        // code thực thi trong vòng lặp
    }
    
  7. Tránh Sử Dụng Infinite Loops: Kiểm tra xem vòng lặp của bạn có khả năng trở thành vòng lặp vô hạn không. Đảm bảo rằng điều kiện dừng sẽ trở thành false tại một thời điểm nào đó.

    for (int i = 0; i >= 0; i++) {
        // Code thực thi trong vòng lặp
    }
    

Những lưu ý này giúp bạn sử dụng vòng lặp "for" một cách an toàn và hiệu quả trong code của mình, tránh lỗi và giữ code dễ đọc và bảo trì.

Lời kết

Vòng lặp "for" là một công cụ mạnh mẽ và phổ biến trong lập trình Java. Nó cho phép bạn lặp lại các công việc nhiều lần, duyệt qua mảng và danh sách, và thực hiện nhiều thuật toán quan trọng. Bằng cách hiểu cấu trúc và cách hoạt động của vòng lặp "for," bạn có thể viết code hiệu quả và dễ đọc hơn.

Tuy nhiên, khi sử dụng vòng lặp "for," hãy lưu ý các quy tắc và lưu ý quan trọng để tránh các lỗi thường gặp và tối ưu hóa code của bạn. Điều này bao gồm việc đặt tên biến rõ ràng, kiểm tra các điều kiện dừng, và kiểm tra biên đổi khi duyệt qua mảng hoặc danh sách. Hãy luôn kiểm tra và tối ưu hóa code của bạn để đảm bảo rằng nó hoạt động đúng và hiệu quả.

Code trong bài viết này đã cung cấp ví dụ về cách sử dụng vòng lặp "for" trong các tình huống khác nhau, từ việc in các số đến xử lý đồ thị và thuật toán tối ưu. Hi vọng rằng thông qua việc học và thực hành, bạn có thể sử dụng vòng lặp "for" một cách thành thạo và ứng dụng chúng trong các dự án lập trình thực tế của mình.


©️ Tác giả: Trần Quang Hiệp từ Viblo


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí