Phương Thức Equals() Và Phương Thức Hash Code Là Gì ? Java — Việc Sử Dụng Hashcode Trong Java Là Gì

Bài viết này giúp bạn hiểu khái niệm 2 phương thức quan trọng: Phương thức equals() và hashCode() trong Java.

*
Khi sử dụng những collection, Để nhận được những hành vi mong ước, tất cả chúng ta nên ghi đè những phương pháp equals ( ) và hashCode ( ) trong những lớp của những thành phần được thêm vào collection .
Lớp Object ( lớp cha của toàn bộ những lớp trong Java ) định nghĩa hai phương pháp equal ( ) và hashCode ( ). Điều đó có nghĩa là tổng thể những lớp trong Java ( gồm có cả những lớp bạn đã tạo ) thừa kế những phương pháp này. Về cơ bản, lớp Object triển khai những phương pháp này cho mục tiêu chung .

Tuy nhiên, bạn sẽ phải ghi đè chúng một cách cụ thể cho các lớp có đối tượng được thêm vào các collection, đặc biệt là các collection dựa trên bảng băm như HashSet và HashMap.

Đang xem : Hash code là gì
Nội dung chính
Phương thức equals ( ) trong JavaCác quy tắc cho phương pháp equals ( ) và hashCode ( ) trong Java

Phương thức equals() trong Java

Khi so sánh hai đối tượng người tiêu dùng với nhau, Java gọi phương pháp equals ( ) của chúng trả về true nếu hai đối tượng người dùng bằng nhau hoặc false nếu hai đối tượng người tiêu dùng là khác nhau. Lưu ý rằng phép so sánh sử dụng phương pháp 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 setup phương pháp equals ( ) trong lớp Object so sánh những tham chiếu của hai đối tượng người dùng. Điều đó có nghĩa là bạn nên ghi đè nó trong những lớp của bạn để so sánh ngữ nghĩa. Hầu hết những lớp trong JDK ghi đè phương pháp equals ( ) của riêng chúng, ví dụ điển hình như String, Date, Integer, Double, v.v.

Ví dụ phương thức equals() của đối tượng String

Ví dụ nổi bật so sánh chuỗi trong Java, để thấy sự khác nhau giữa phương pháp equal ( ) và toán tử = = .

package vn.cungdaythang.com;public class EqualExample1 { public static void main(String<> args) { String s1 = new String(“This is a string”); String s2 = new String(“This is a string”); System.out.println(“s1 == s2: ” + (s1 == s2)); System.out.println(“s1.equals(s2): ” + (s1.equals(s2))); }}
Kết quả:

s1 == s2: falses1.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.

Ví dụ ghi đè phương thức equals()

Tương tự như vậy, giả sử tất cả chúng ta có lớp Student và thiết lập phương pháp equal ( ) như sau :
Trong thực tiễn, tất cả chúng ta hoàn toàn có thể xem xét hai đối tượng người tiêu dùng Student có ngữ nghĩa tương tự 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 pháp equals ( ) trong lớp này để xác nhận rằng hai đối tượng người dùng Student có những thuộc tính giống nhau được coi là bằng nhau :

package vn.cungdaythang.com;public class Student { private String id; private String name; private String email; private int age; public Student(String id, String name, String email, int age) { this.id = id; this.name = name; this.email = email; this.age = age; } public String toString() { String studentInfo = “Student ” + id; studentInfo += “: ” + name; studentInfo += ” – ” + email; studentInfo += ” – ” + age; return studentInfo; } public boolean equals(Object obj) { if (obj instanceof Student) { Student another = (Student) obj; if (this.id.equals(another.id) && this.name.equals(another.name) && this.email.equals(another.email) && this.age == another.age) { return true; } } return false; }}
Tạo ra lớp EqualStudent.java để kiểm tran phương thức equal() trong lớp Student.

package vn.cungdaythang.com;public class EqualStudent { public static void main(String<> args) { Student student1 = new Student(“123”, “Cong”, “cong
gmail.com”, 22); Student student2 = new Student(“123”, “Cong”, “cong
gmail.com”, 22); Student student3 = new Student(“456”, “Dung”, “dung
gmail.com”, 18); System.out.println(“student1 == student2: ” + (student1 == student2)); System.out.println(“student1.equals(student2): ” + (student1.equals(student2))); System.out.println(“student2.equals(student3): ” + (student2.equals(student3))); }}
Kết quả:

student1 = = student2 : falsestudent1.equals ( student2 ) : truestudent2.equals ( student3 ) : false

Ví dụ ghi đè phương thức equals() của phần tử của collection

Ta có lớp Student. java có nội dung như sau :

package vn.cungdaythang.com;public class Student { private String id; private String name; private String email; private int age; public Student(String id) { this.id = id; } public Student(String id, String name, String email, int age) { this.id = id; this.name = name; this.email = email; this.age = age; } public String toString() { String studentInfo = “Student ” + id; studentInfo += “: ” + name; studentInfo += ” – ” + email; studentInfo += ” – ” + age; return studentInfo; } public boolean equals(Object obj) { if (obj instanceof Student) { Student another = (Student) obj; if (this.id.equals(another.id)) { return true; } } return false; }}
Ở đâ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 người tiêu dùng Student có một ID duy nhất, và xem hai đối tượng người dù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 hoàn toàn có thể được sử dụng để kiểm tra nếu đối tượng người tiêu dùng được chỉ định sống sót trong list. Về thực chất, phương pháp equal ( ) được gọi bên trong phương pháp contains ( Object ) .

package vn.cungdaythang.com;import java.util.ArrayList;import java.util.List;public class EqualStudent2 { public static void main(String<> args) { Student student1 = new Student(“123”, “Cong”, “cong
gmail.com”, 22); Student student2 = new Student(“123”, “Cong”, “cong
gmail.com”, 22); Student student3 = new Student(“456”, “Dung”, “dung
gmail.com”, 18); // tạo danh sách student List listStudents = new ArrayList(); // thêm các đối tượng student vào listStudents listStudents.add(student1); listStudents.add(student2); listStudents.add(student3); // tạo các đối tượng student chỉ có thuộc tính ID Student searchStudent1 = new Student(“123”); Student searchStudent4 = new Student(“789”); // tìm kiếm student trong danh sách System.out.println(“Search student1: ” + listStudents.contains(searchStudent1)); System.out.println(“Search student4: ” + listStudents.contains(searchStudent4)); }}
Kết quả:

Search student1 : trueSearch student4 : false

Phương thức hashCode() trong Java

Định nghĩa phương pháp hashCode ( ) trong lớp Object :

public native int hashCode ( ) ;
Xem thêm : Selectors Trong Css Selector Là Gì ? 8 Loại Css Selector Cần Biết

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 những collection dựa trên bảng băm như Hashtable, HashSet và HashMap để tàng trữ những đối tượng người tiêu dùng trong những container nhỏ được gọi là “ nhóm ”. Mỗi nhóm được link với mã băm và mỗi nhóm chỉ chứa những đối tượng người dùng có mã băm giống hệt nhau .
Nói cách khác, một bảng băm nhóm những thành phần của nó bằng những giá trị mã băm của chúng. Sự sắp xếp này giúp cho bảng băm xác định một thành phần một cách nhanh gọn và hiệu suất cao bằng cách tìm kiếm trên những phần nhỏ của collection thay vì hàng loạt collection .
Dưới đây là những bước để xác định một thành phần trong một bảng băm :
Nhận giá trị mã băm của thành phần được chỉ định bằng cách gọi phương pháp hashCode ( ). Tìm nhóm thích hợp được link với mã băm đó. Bên trong nhóm, tìm thành phần đúng chuẩn bằng cách so sánh thành phần được chỉ định với tổng thể những thành phần trong nhóm. Bằng phương pháp equals ( ) của thành phần đã chỉ định được gọi .
Có nói rằng, khi tất cả chúng ta thêm những đối tượng người tiêu dùng của một lớp vào một collection dựa trên bảng băm ( HashSet, HashMap ), phương pháp hashCode ( ) của lớp được gọi để tạo ra một số nguyên ( hoàn toà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 để tàng trữ và xác định những đối tượng người dùng một cách nhanh gọn và hiệu suất cao, vì collection dựa trên bảng băm không duy trì thứ tự những thành phần của nó .
LƯU Ý : Việc thực thi phương pháp mặc định hashCode ( ) trong lớp Object trả về 1 số ít nguyên là địa chỉ bộ nhớ của đối tượng người tiêu dùng. Bạn nên ghi đè phương pháp trong những lớp của bạn. Hầu hết những lớp trong JDK ghi đè phương pháp hashCode ( ) của riêng chúng, ví dụ điển hình như String, Date, Integer, Double, v.v.

Các quy tắc cho phương thức equals() và hashCode() trong Java

Như đã lý giải ở trên, collection dựa trên bảng băm xác lập một thành phần bằng cách gọi phương pháp hashCode ( ) và equals ( ) của nó, thế cho nên khi ghi đè những phương pháp này tất cả chúng ta phải tuân theo những quy tắc sau :
Khi phương pháp equals ( ) được ghi đè, phương pháp hashCode ( ) cũng phải được ghi đè. Nếu hai đối tượng người dùng bằng nhau, mã băm của chúng phải bằng nhau. Nếu hai đối tượng người tiêu dùng không bằng nhau, không có ràng buộc về mã băm của chúng ( mã băm của chúng hoàn toàn có thể bằng nhau hay không ). Nếu hai đối tượng người dùng có mã băm giống nhau, thì không có ràng buộc nào về sự bình nhau của chúng ( chúng hoàn toàn có thể bằng nhau hay không ). Nếu hai đối tượng người dùng có mã băm khác nhau, chúng không được bằng nhau .
Nếu tất cả chúng ta vi phạm những quy tắc này, những collection sẽ hoạt động giải trí hoàn toàn có thể không đúng như những đối tượng người tiêu dùng không hề tìm thấy, hoặc những đối tượng người tiêu dùng sai được trả về thay vì những đối tượng người dùng đúng chuẩn .

Ví dụ ghi đề phương thức equals(), không ghi đè hashCode()

Hãy xem phương pháp hashCode ( ) và equals ( ) ảnh hưởng tác động như thế nào đến hành vi của một đối tượng người tiêu dùng Set .
Lớp Student. java

package vn.cungdaythang.com;public class Student { private String id; private String name; private String email; private int age; public Student(String id) { this.id = id; } public Student(String id, String name, String email, int age) { this.id = id; this.name = name; this.email = email; this.age = age; } public String toString() { String studentInfo = “Student ” + id; studentInfo += “: ” + name; studentInfo += ” – ” + email; studentInfo += ” – ” + age; return studentInfo; } public boolean equals(Object obj) { if (obj instanceof Student) { Student another = (Student) obj; if (this.id.equals(another.id)) { return true; } } return false; }}
Lớp EqualStudent3 .java

package vn.cungdaythang.com;import java.util.HashSet;import java.util.Set;public class EqualStudent3 { public static void main(String<> args) { Student student1 = new Student(“123”, “Cong”, “cong
gmail.com”, 22); Student student2 = new Student(“123”, “Cong”, “cong
gmail.com”, 22); Student student3 = new Student(“456”, “Dung”, “dung
gmail.com”, 18); Set setStudents = new HashSet(); setStudents.add(student1); setStudents.add(student2); setStudents.add(student3); // in các phần tử của set ra màn hình for (Student student : setStudents) { System.out.println(student); } }}
Kết quả:

Student 456: Dung – dung
gmail.com – 18Student 123: Cong – cong
gmail.com – 22Student 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 những phương pháp equals ( ) và hashCode ( ) trên mỗi đối tượng người dùng được thêm vào để bảo vệ không có sự trùng lặp. Trong trường hợp của tất cả chúng ta, lớp Student chỉ ghi đè phương pháp equals ( ). Và phương pháp hashCode ( ) thừa kế từ lớp Object trả về những địa chỉ bộ nhớ của mỗi đối tượng người tiêu dùng không đồng điệu với phương pháp equals ( ). Do đó, đối tượng người dùng Set giải quyết và xử lý đối tượng người dùng student1 và student2 thành hai thành phần khác nhau .
Bây giờ, tất cả chúng ta hãy ghi đè phương pháp hashCode ( ) trong lớp Student như sau :

public int hashCode() { return 31 + id.hashCode(); }
Kết quả:

Student 123: Cong – cong
gmail.com – 22Student 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 những phương pháp equals ( ) và hashCode ( ) được ghi đè đúng cách, tất cả chúng ta cũng hoàn toàn có thể triển khai tìm kiếm trên tập hợp như sau :

Student searchStudent = new Student(“456”);boolean found = setStudents.contains(searchStudent);System.out.println(“Search student: ” + found);
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 những phương pháp equals ( ) và hashCode ( ). Và vận dụng chúng cho những collection .

Tham khảo

https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode–
Lớp Object trong java

Xem thêm : # 999 Stt Hay Về Tình Yêu Tiếng Anh Ngắn Ngọn và Hay Về Tình Yêu
Collection trong java