Phương thức equals() và phương thức hashCode() là những phương thức rất quan trọng đối với tất cả các đối tượng trong lập trình Java. Trong bài viết này, mình sẽ trình bày với tất cả các bạn những kiến thức cơ bản về hai phương thức này các bạn nhé!
Mặc định, các phương thức này được định nghĩa trong đối tượng Object, là đối tượng cha của tất cả các đối tượng trong Java. Nhưng để sử dụng đúng mục đích của 2 phương thức này, chúng ta cần override lại chúng trong các đối tượng của chúng ta.
Phương thức equals()
Phương thức này dùng để kiểm tra 2 đối tượng bất kỳ có bằng nhau hay không?
Như các bạn đã biết, trong Java chúng ta có 2 kiểu dữ liệu cơ bản là primitive và object. Đối với các biến primitive, chúng ta có thể sử dụng toán tử “==” để so sánh giữa hai biến bất kỳ, ví dụ như:
1 2 3 4 5 6 7 8 9 10 11 |
package com.huongdanjava.example; public class Example { public static void main(String[] args) { int b = 2; int c = 2; System.out.println(b == c); } } |
Kết quả:
Nhưng đối với kiểu dữ liệu object thì bắt buộc chúng ta phải override lại phương thức equals() trong đối tượng Object để so sánh xem 2 đối tượng cùng class có bằng nhau hay không?
Ví dụ, mình có đối tượng Student 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 38 39 40 41 42 |
package com.huongdanjava.example; public class Student { private String firstName; private String middleName; private String lastName; private String country; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getMiddleName() { return middleName; } public void setMiddleName(String middleName) { this.middleName = middleName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } } |
Bây giờ, mình sẽ sử dụng phương thức equals() mà đối tượng Student kế thừa từ đối tượng Object để so sánh xem liệu 2 đối tượng Student có cùng firstName, middleName, lastName và country có bằng nhau hay không các bạn nhé!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package com.huongdanjava.example; public class Example { public static void main(String[] args) { Student student1 = new Student(); student1.setFirstName("Khanh"); student1.setMiddleName("Huu"); student1.setLastName("Nguyen"); student1.setCountry("Viet Nam"); Student student2 = new Student(); student2.setFirstName("Khanh"); student2.setMiddleName("Huu"); student2.setLastName("Nguyen"); student2.setCountry("Viet Nam"); System.out.println(student1.equals(student2)); } } |
Kết quả:
Như các bạn thấy, mặc dù 2 Students có cùng tên và country nhưng Java vẫn không xem chúng là một. Để giải quyết vấn đề này, chúng ta sẽ override lại phương thức equals() trong đối tượng Student 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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
package com.huongdanjava.example; public class Student { private String firstName; private String middleName; private String lastName; private String country; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getMiddleName() { return middleName; } public void setMiddleName(String middleName) { this.middleName = middleName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Student other = (Student) obj; if (country == null) { if (other.country != null) return false; } else if (!country.equals(other.country)) return false; if (firstName == null) { if (other.firstName != null) return false; } else if (!firstName.equals(other.firstName)) return false; if (lastName == null) { if (other.lastName != null) return false; } else if (!lastName.equals(other.lastName)) return false; if (middleName == null) { if (other.middleName != null) return false; } else if (!middleName.equals(other.middleName)) return false; return true; } } |
Trong phương thức equals() được override ở trên, mình đã kiểm tra tất cả các thuộc tính của đối tượng Student. Chỉ khi nào tất cả các thuộc tính của 2 đối tượng student1 và student2 giống nhau thì phương thức này mới trả về true. Và khi đó, Java sẽ xem 2 đối tượng này là bằng nhau.
Khi đó kết quả sẽ là:
Phương thức hashCode()
Các đối tượng như HashMap, HashTable sử dụng các đối tượng key để tìm kiếm các đối tượng value tương ứng. Và để tối ưu cho việc tìm kiếm, Java sử dụng các hash value lấy từ phương thức hashCode() của các đối tượng key để gom nhóm các đối tượng này trong những cái gọi là các bucket. Mỗi bucket tương ứng với một giá trị hash value.
Khi tìm kiếm một đối tượng bất kỳ trong HashMap hay HashTable, đầu tiên Java sẽ lấy hash value của đối tượng key mà chúng ta muốn tìm kiếm. Sau đó nó sẽ kiểm tra các bucket để xem giá trị hash value đó có trùng khớp với bucket nào hay không. Nếu thoả mãn một bucket nào đó thì Java sẽ trả về giá trị của đối tượng value mà chúng ta muốn tìm kiếm.
Nhiều đối tượng có thể có cùng hash value, và do đó chúng có thể nằm chung một bucket. Trong trường hợp này, Java sẽ sử dụng tiếp phương thức equals() để tìm chính xác đối tượng value mà chúng ta muốn tìm kiếm.
Ở đây chúng ta có một khái niệm gọi là contract giữa phương thức equals() và phương thức hashCode() đó là:
- Nếu hai đối tượng là bằng nhau thì chúng phải có cùng hashCode().
- Nếu hai đối tượng có cùng hashCode() thì chúng có thể bằng nhau hoặc là không.