Trong Java, nếu bạn muốn kiểm tra một đối tượng có tồn tại trong một tập hợp hay không, bạn phải so sánh từng đối tượng trong tập hợp đó. Điều này có thể dẫn đến hiệu suất kém khi số lượng đối tượng lớn. Để cải thiện hiệu suất, thuật toán Hash được sử dụng. Thuật toán Hash tính toán một mã Hash cho mỗi đối tượng và phân phối chúng vào các vùng lưu trữ tương ứng. Ví dụ, trong một tập hợp chứa nhiều người, những người có quốc tịch Trung Quốc sẽ nằm ở một vùng riêng, người Mỹ ở một vùng khác, v.v.
Java cung cấp lớp HashSet để triển khai cơ chế Hash. Khi tìm kiếm một đối tượng trong HashSet, đầu tiên nó sử dụng phương thức hashCode() để tính toán mã Hash của đối tượng, sau đó dùng phương thức equals() để tìm kiếm trong vùng lưu trữ tương ứng. Do đặc điểm của tập hợp, mỗi đối tượng chỉ xuất hiện một lần duy nhất.
Ví dụ về sử dụng HashSet:
package example;
import java.util.HashSet;
import java.util.Set;
class Human {
// Giới tính
String gender;
// Tên
String name;
// Chiều cao
Double height;
// Cân nặng
Double weight;
public Human(String n, String g, Double h, Double w) {
this.name = n;
this.gender = g;
this.height = h;
this.weight = w;
}
public String toString() {
return "\nTên: " + this.name + " Giới tính: " + this.gender + " Chiều cao: " + this.height + " Cân nặng: " + this.weight;
}
}
public class ExampleHS {
private static Set<Human> humanSet = new HashSet<Human>();
public static void main(String[] args) {
humanSet.add(new Human("John", "Male", 175.0, 72.0));
humanSet.add(new Human("Mary", "Female", 168.0, 63.0));
humanSet.add(new Human("Paul", "Male", 180.0, 75.0));
humanSet.add(new Human("Anna", "Female", 165.0, 60.0));
humanSet.add(new Human("Paul", "Male", 180.0, 75.0)); // Thêm cùng một đối tượng
System.out.println(humanSet);
}
}
Trong ví dụ trên, mặc dù đã thêm Paul hai lần, nhưng do chưa override phương thức equals() và hashCode(), kết quả in ra vẫn hiển thị Paul hai lần. Vì vậy, cần phải override phương thức equals():
// Override phương thức equals()
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Human)) return false;
Human other = (Human) obj;
return this.name.equals(other.name) && this.gender.equals(other.gender);
}
Sau khi override equals(), cần phải override luôn phương thức hashCode():
// Override phương thức hashCode()
public int hashCode() {
return this.name.hashCode();
}
Kết quả cuối cùng là mỗi đối tượng sẽ chỉ xuất hiện một lần trong tập hợp. Nếu hai đối tượng có cùng tên và giới tính, thì chúng sẽ được coi là trùng nhau và chỉ được thêm một lần.