Menu
CoddyTech

equals() và hashCode()

Thuộc phần Lập trình hướng đối tượng trong hành trình Java của Coddy. Bài học 42 trên 87.

Khi so sánh các đối tượng trong Java, toán tử == kiểm tra xem hai tham chiếu có trỏ đến cùng một vị trí bộ nhớ hay không. Để so sánh nội dung thực tế của các đối tượng, bạn cần ghi đè phương thức equals().

public class Person {
    private String name;
    private int age;
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj;
        return age == person.age && name.equals(person.name);
    }
}

Phương thức equals() tuân theo một mẫu chuẩn: trước tiên, kiểm tra xem đó có phải cùng một đối tượng không, sau đó xác minh kiểu dữ liệu, cuối cùng so sánh các trường liên quan.

Mỗi khi ghi đè equals(), bạn cũng phải ghi đè hashCode(). Đây là một quy tắc trong Java: các đối tượng bằng nhau phải có cùng mã băm. Các bộ sưu tập dựa trên mã băm như HashMap và HashSet dựa vào quy tắc này để hoạt động chính xác.

@Override
public int hashCode() {
    return Objects.hash(name, age);
}

Phương thức tiện ích Objects.hash() tạo mã băm từ cùng các trường được dùng trong equals(). Nếu hai đối tượng Person có cùng tên và tuổi, chúng sẽ được xem là bằng nhau và tạo ra mã băm giống hệt nhau, giúp đảm bảo hành vi nhất quán trong các tập hợp.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống lưu hồ sơ sinh viên triển khai đúng cách việc so sánh hai đối tượng. Bạn sẽ tạo lớp Student, trong đó hai sinh viên được xem là bằng nhau nếu có cùng mã sinh viên và tên, bất kể chúng có phải là cùng một đối tượng trong bộ nhớ hay không.

Bạn sẽ sắp xếp code trong hai tệp:

  • Student.java: Tạo một lớp đại diện cho sinh viên với ba trường riêng tư: studentId (String), name (String) và gpa (double). Thêm hàm khởi tạo để khởi tạo tất cả các trường và các phương thức getter cho từng trường.

    Ghi đè phương thức equals() để hai đối tượng Student được xem là bằng nhau khi có cùng studentId VÀ cùng name. Làm theo mẫu chuẩn: kiểm tra xem có cùng tham chiếu hay không, kiểm tra giá trị null và kiểu, sau đó so sánh các trường liên quan.

    Ghi đè phương thức hashCode() bằng Objects.hash() với cùng các trường được dùng trong equals(). Nhớ import java.util.Objects ở đầu tệp.

  • Main.java: Dùng lớp Student để so sánh các đối tượng sinh viên. Bạn sẽ nhận sáu đầu vào đại diện cho hai sinh viên: mã sinh viên, tên và GPA của sinh viên thứ nhất, tiếp theo là mã sinh viên, tên và GPA của sinh viên thứ hai.

    Tạo cả hai đối tượng Student, sau đó thực hiện ba phép so sánh và in kết quả:

    1. In Same reference: , theo sau là kết quả cho biết sinh viên thứ nhất có bằng chính nó hay không (kết quả luôn phải là true)
    2. In Content equality: , theo sau là kết quả cho biết sinh viên thứ nhất có bằng sinh viên thứ hai hay không (dựa trên cách bạn triển khai equals)
    3. In Hash codes match: , theo sau là kết quả cho biết hai sinh viên có cùng mã băm hay không

Bạn sẽ nhận sáu đầu vào: mã sinh viên thứ nhất (String), tên sinh viên thứ nhất (String), GPA của sinh viên thứ nhất (double), mã sinh viên thứ hai (String), tên sinh viên thứ hai (String) và GPA của sinh viên thứ hai (double).

Hãy chú ý rằng khi hai sinh viên có mã và tên trùng khớp, cả equals() đều trả về true VÀ mã băm của họ cũng trùng khớp. Đây là quy tắc bạn phải duy trì!

Tự làm thử

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Đọc dữ liệu của sinh viên thứ nhất
        String id1 = scanner.nextLine();
        String name1 = scanner.nextLine();
        double gpa1 = scanner.nextDouble();
        scanner.nextLine(); // đọc bỏ ký tự xuống dòng
        
        // Đọc dữ liệu của sinh viên thứ hai
        String id2 = scanner.nextLine();
        String name2 = scanner.nextLine();
        double gpa2 = scanner.nextDouble();
        
        // TODO: Tạo hai đối tượng Student từ dữ liệu đầu vào
        
        // TODO: In ra "Same reference: ", sau đó in kết quả so sánh student1 với chính nó
        
        // TODO: In ra "Content equality: ", sau đó in kết quả so sánh student1 với student2
        
        // TODO: In ra "Hash codes match: ", sau đó in kết quả kiểm tra hai sinh viên có cùng mã băm hay không
    }
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch Java online