equals() và hashCode() trong Java

Chào mừng các bạn đã quay trở lại với thachleblog, cũng lâu lắm rồi chúng ta chưa gặp nhau nhỉ. Mấy nay người oải oải, làm về là nằm luôn, chả buồn mở máy tính. Khó khăn lắm mới chiến thắng “con quỷ lười” để viết bài hôm nay 😆 Bài viết hôm nay mình sẽ giới thiệu với các bạn hai phương thức equals() và hashCode() đồng thời tìm hiểu về mục đích sử dụng của chúng trong Hash collections cụ thể là HashTable. Vấn đề này mình cũng đã từng gặp trong các buổi phỏng vấn, cũng là kinh nghiệm để chia sẻ với các bạn. Chúng ta cùng bắt đầu nhé.

equals() và hashCode()

equals()

Phương thức equals() trả về kết quả phép so sánh ==. Tuy nhiên, thông thường equals() được override để so sánh object. Cụ thể trong String, equals() override để so sánh chuỗi các ký tự. Các bạn có thể xem chi tiết implement của equals() trong class String

Ví dụ so sánh String

  1. String str1 = new String("test");
  2. String str2 = new String("test");   
  3. if (str1.equals(str2)) // return true
  4. if ("test".equals(str1)) // return true

Bởi vì 2 object đều có các kí tự là “test” là đó kết quả của biểu thức là true.

Trong collections, equals() được sử dụng để tìm xem trong collections có chứa element đó hay không.

Ví dụ:

  1. List list = new ArrayList();
  2. list.add("123");
  3. boolean contains123 = list.contains("123");

Arraylist sẽ thực thi biểu thức “123”.equals(element) với lần lượt tất cả các element khác để tìm element có giá trị là “123”. Nếu có sẽ trả về giá trị là true, ngược lại sẽ trả về giá trị là false.

Vậy khi nào 2 object equals() trả về giá trị true? Tương tự với object String, kết quả phụ thuộc vào cách chúng ta implement phương thức equals()

Ví dụ:

public class Employee {
   protected long   employeeId;
   protected String firstName;
   protected String lastName;
}
 
public Employee(){
  this.employeeId = 1;
  this.firstName = "Thach";
  this.lastName = "Le";
}
 
public boolean equals(Object o){
   if(o == null)                return false;
   if(!(o instanceof Employee)) return false;
 
   Employee other = (Employee) o;
   if(this.employeeId != other.employeeId)      return false;
   if(! this.firstName.equals(other.firstName)) return false;
   if(! this.lastName.equals(other.lastName))   return false;
 
   return true;
 }

Như cách implement ở trên, phương thức equals() 2 object employee sẽ trả về kết quả true khi kết quả String equals() id, firstName, lastName là true.

hashCode()

hashCode() sẽ trả về giá trị int khi object được khởi tạo. Giá trị này là random cho mỗi object nếu phương thức hashCode() không được override

Phương thức hashCode() được sử dụng khi chúng ta insert object vào HashTable, HashMap hoặc HashSet.

Khi insert một object vào hashtable, phương thức hashCode() sẽ trả về giá trị hash code của object, và giá trị này được sử dụng để xác định vị trí của object được lưu trữ trong hashtable. Tương tự Khi chúng ta get object từ hashtable, giá trị hash code này được sử dụng để tìm nơi lưu trữ của object trong hashtable.

Hình minh họa cấu trúc Hash Map, giá trị hash code được hiểu như địa chỉ của các ô chứa bên trong Hash Map

equals() và hashCode() trong Hash collections

Như phân tích ở trên, Hash collection sẽ sử dụng hashCode() để xác định được “vị trí” của object và equals() để xác định chính xác object cần tìm.

Tuy nhiên, cơ chế optimize của Hash collections sẽ không xét đến equals() khi 2 object không có cùng hashCode().

Ví dụ:

Map<Object, String> mapEmployee = new HashMap<>();
		mapEmployee.put(new Employee(), "Secret code 1");		
		System.out.println("Secret code: " + mapEmployee.get(new Employee()));

Kết quả trả về sẽ là null do class Employee không override method hashCode(). Vì vậy lưu ý là:

  • Luôn luôn override method hashCode() khi override equals().
  • Nếu 2 object equals() là true thì sẽ có cùng hashcode() tuy nhiên nếu 2 object có cùng hash code sẽ không đảm bảo là kết quả equals sẽ là true.

Sẽ có bài về cấu trúc dữ liệu Map, mình sẽ nói rõ hơn về hàm “băm” và cơ chế của hash function, các bạn nhớ đón đọc nhé.

Lâu rồi mới viết lại, viết nhiêu đây thôi 😛 . Mọi góp ý về nội dung vui lòng comment bên dưới, mình sẽ follow. Hẹn gặp lại các bạn ở các bài viết sau nhé. Xin cảm ơn.

Tham khảo thêm:
https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html
http://tutorials.jenkov.com/java-collections/hashcode-equals.html