Khi so sánh hai đối tượng với nhau, Java gọi phương thức equals() của chúng trả về true nếu hai đối tượng bằng nhau hoặc false nếu hai đối tượng là khác nhau. Lưu ý rằng phép so sánh sử dụng phương thức equals() so với sử dụng toán tử == là khác nhau.
Đây là sự khác biệt:
Phương thức equals() được thiết kế để so sánh hai đối tượng về mặt ngữ nghĩa (bằng cách so sánh các thành viên dữ liệu của lớp), trong khi toán tử == so sánh hai đối tượng về mặt kỹ thuật (bằng cách so sánh các tham chiếu của chúng, nghĩa là địa chỉ bộ nhớ).
LƯU Ý: Việc cài đặt phương thức equals() trong lớp Object so sánh các tham chiếu của hai đối tượng. Điều đó có nghĩa là bạn nên ghi đè nó trong các lớp của bạn để so sánh ngữ nghĩa. Hầu hết các lớp trong JDK ghi đè phương thức equals() của riêng chúng, chẳng hạn như String, Date, Integer, Double, v.v.
Ví dụ điển hình so sánh chuỗi trong Java, để thấy sự khác nhau giữa phương thức equal() và toán tử ==.
1 2 3 4 5 6 7 8 9 10 11 |
|
Kết quả:
s1 == s2: false s1.equals(s2): true
So sánh tham chiếu (toán tử ==) trả về false vì s1 và s2 là hai đối tượng khác nhau được lưu trữ ở các vị trí khác nhau trong bộ nhớ. Trong khi so sánh ngữ nghĩa trả về true bởi vì s1 và s2 có cùng giá trị (“THis is a string”) có thể được coi là bằng nhau về mặt ngữ nghĩa.
Tương tự như vậy, giả sử chúng ta có lớp Student và cài đặt phương thức equal() như sau:
Trong thực tế, chúng ta có thể xem xét hai đối tượng Student có ngữ nghĩa tương đương nhau nếu chúng có cùng thuộc tính (id, name, email và age). Bây giờ, hãy xem cách ghi đè phương thức equals() trong lớp này để xác nhận rằng hai đối tượng Student có các thuộc tính giống nhau được coi là bằng nhau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
|
Tạo ra lớp EqualStudent.java để kiểm tran phương thức equal() trong lớp Student.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Kết quả:
student1 == student2: false student1.equals(student2): true student2.equals(student3): false
Ta có lớp Student.java có nội dung như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
|
Ở đây, phương thức equals() này chỉ so sánh thuộc tính ID của hai đối tượng Student.
Chúng ta sẽ coi mỗi đối tượng Student có một ID duy nhất, và xem hai đối tượng sinh viên là bằng nhau nếu chúng có ID giống nhau.
Phương thức contains(Object) của interface List trong java có thể được sử dụng để kiểm tra nếu đối tượng được chỉ định tồn tại trong danh sách. Về bản chất, phương thức equal() được gọi bên trong phương thức contains(Object).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
Kết quả:
Search student1: true Search student4: false
Định nghĩa phương thức hashCode() trong lớp Object:
1 |
|
Bạn có thể thấy phương thức này trả về một số nguyên. Vậy nó được sử dụng ở đâu?
Đây là bí mật:
Số băm này được sử dụng bởi các collection dựa trên bảng băm như Hashtable , HashSet và HashMap để lưu trữ các đối tượng trong các container nhỏ được gọi là "nhóm". Mỗi nhóm được liên kết với mã băm và mỗi nhóm chỉ chứa các đối tượng có mã băm giống hệt nhau.
Nói cách khác, một bảng băm nhóm các phần tử của nó bằng các giá trị mã băm của chúng. Sự sắp xếp này giúp cho bảng băm định vị một phần tử một cách nhanh chóng và hiệu quả bằng cách tìm kiếm trên các phần nhỏ của collection thay vì toàn bộ collection.
Dưới đây là các bước để định vị một phần tử trong một bảng băm:
Có nói rằng, khi chúng ta thêm các đối tượng của một lớp vào một collection dựa trên bảng băm (HashSet, HashMap ), phương thức hashCode() của lớp được gọi để tạo ra một số nguyên (có thể là một giá trị tùy ý). Con số này được sử dụng bởi bộ sưu tập để lưu trữ và định vị các đối tượng một cách nhanh chóng và hiệu quả, vì collection dựa trên bảng băm không duy trì thứ tự các phần tử của nó.
LƯU Ý: Việc thực thi phương thức mặc định hashCode() trong lớp Object trả về một số nguyên là địa chỉ bộ nhớ của đối tượng. Bạn nên ghi đè phương thức trong các lớp của bạn. Hầu hết các lớp trong JDK ghi đè phương thức hashCode() của riêng chúng, chẳng hạn như String , Date , Integer , Double , v.v.
Như đã giải thích ở trên, collection dựa trên bảng băm xác định một phần tử bằng cách gọi phương thức hashCode() và equals() của nó, vì vậy khi ghi đè các phương thức này chúng ta phải tuân theo các quy tắc sau:
Nếu chúng ta vi phạm các quy tắc này, các collection sẽ hoạt động có thể không đúng như các đối tượng không thể tìm thấy, hoặc các đối tượng sai được trả về thay vì các đối tượng chính xác.
Hãy xem phương thức hashCode() và equals() ảnh hưởng như thế nào đến hành vi của một đối tượng Set.
Lớp Student.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
|
Lớp EqualStudent3 .java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
Kết quả:
Student 456: Dung - dung@gmail.com - 18 Student 123: Cong - cong@gmail.com - 22 Student 123: Cong - cong@gmail.com - 22
Hãy nhìn xem, bạn có nhận thấy rằng có 2 sinh viên trùng lặp (ID: 123), phải không?
Đây là lý do:
Tập Set gọi các phương thức equals() và hashCode() trên mỗi đối tượng được thêm vào để đảm bảo không có sự trùng lặp. Trong trường hợp của chúng ta, lớp Student chỉ ghi đè phương thức equals(). Và phương thức hashCode() thừa kế từ lớp Object trả về các địa chỉ bộ nhớ của mỗi đối tượng không nhất quán với phương thức equals(). Do đó, đối tượng Set xử lý đối tượng student1 và student2 thành hai phần tử khác nhau.
Bây giờ, chúng ta hãy ghi đè phương thức hashCode() trong lớp Student như sau:
1 2 3 |
|
Kết quả:
Student 123: Cong - cong@gmail.com - 22 Student 456: Dung - dung@gmail.com - 18
Good! Phần tử trùng lặp hiện đã bị xóa. Đó chính là điều chúng tôi muốn.
Với các phương thức equals() và hashCode() được ghi đè đúng cách, chúng ta cũng có thể thực hiện tìm kiếm trên tập hợp như sau:
1 2 3 |
|
Kết quả:
Search student: true
Để tự mình thử nghiệm nhiều hơn, hãy thử loại bỏ phương thức equals() hoặc hashCode() và quan sát kết quả.
Hy vọng bài này giúp bạn hiểu cách sử dụng các phương thức equals() và hashCode(). Và áp dụng chúng cho các collection.
Nguồn tin: viettuts.vn