Khi cần lưu trữ các phần tử riêng biệt trong Java vào một tập hợp nào đó, chúng ta thường nghĩ ngay tới việc sử dụng Set. HashSet và LinkedHashSet đều là các tập hợp (set) trong Java, được sử dụng để lưu trữ các phần tử duy nhất mà không theo thứ tự như mảng hoặc danh sách. Mặc dù đều là các triển khai của Interface Set nhưng chúng lại mang nhiều đặc điểm khác biệt. Trong bài viết này, Stringee và các bạn sẽ cùng tìm hiểu về 2 cấu trúc dữ liệu này nhé.
1. Lớp HashSet trong Java
HashSet trong Java là một lớp kế thừa AbstractSet và triển khai Set interface trong Collections Framework, chính vì đó nó sẽ mang các đặc điểm tương đồng với Set. HashSet được sử dụng để tạo một collection với cấu trúc lưu trữ sử dụng bảng băm.
Cấu trúc dữ liệu bảng băm, trong tiếng anh là hash table. Hash table lưu giữ thông tin thông qua một kỹ thuật được gọi là hashing(băm). Trong hashing, nội dung mang tính thông tin của một key được sử dụng để quyết định một value duy nhất được gọi là hash code của nó.
Hash code sau đó được sử dụng như là index, tại đó dữ liệu mà liên kết với key được lưu giữ. Phép biến đổi của key vào trong hashcode của nó được thực hiện tự động.
>>> Xem thêm bài viết:
- Khai báo và sử dụng mảng các đối tượng trong Java
- Phân biệt ArrayList, Set và Vector trong Java
- Lập trình đa luồng là gì? Hướng dẫn lập trình đa luồng bằng ngôn ngữ Java
Ví dụ về HashSet trong Java
public class HashSetMain {
public static void main(String[] args) {
Set<String> languages = new HashSet<String>();
languages.add("Java");
languages.add("Python");
languages.add("Java");
languages.add("PHP");
System.out.println("Size of set: " + languages.size());
System.out.println("Print the set: " + languages);
System.out.println("Set contains Java ? " + languages.contains("Java"));
}
}
Output
Size of set: 3
Print the set: [Java, PHP, Python]
Set contains Java ? true
2. Lớp LinkedHashSet trong Java
LinkedHashSet trong Java là một triển khai của Set, nó có kế thừa HashSet và sử dụng hashtable để lưu giữ dữ liệu.
LinkedHashSet có duy trì thứ tự chèn các phần tử.
Ví dụ về LinkedHashSet trong Java
public static void main(String[] args) {
Set<String> languages = new LinkedHashSet<>();
languages.add("Java");
languages.add("Python");
languages.add("Java");
languages.add("PHP");
System.out.println("Size of set: " + languages.size());
System.out.println("Print the set: " + languages);
System.out.println("Set contains Java ? " + languages.contains("Java"));
}
Output
Size of set: 3
Print the set: [Java, Python, PHP]
Set contains Java ? true
>>> Xem thêm bài viết:
- Tìm hiểu về design pattern factory trong java
- Tìm hiểu về Deadlock trong Java
3. Điểm giống nhau của HashSet và LinkedHashSet
Cả 2 cấu trúc đều không cho phép lưu phần tử trùng lặp(đặc điểm chung của các Set)
Đều là không đồng bộ: non-synchronized, nếu sử dụng trong môi trường multi-threading phải sử dụng synchronize bên ngoài nếu cần.
Đều implement Cloneable và Serializable
Cả 2 đều là fail-fast. Bạn sẽ nhận được ConcurrentModificationException nếu chúng được sửa đổi sau khi tạo đối tượng Iterator.
Các cấu trúc kể trên đều sử dụng các implementation của Map để lưu trữ các phần tử có trong nó.
4. So sánh điểm khác nhau giữa HashSet và LinkedHashSet trong Java
HashSet | LinkedHashSet | |
---|---|---|
Cách thức làm việc? | HashSet sử dụng HashMap nội bộ để lưu trữ các phần tử. | LinkedHashSet sử dụng LinkedHashMap nội bộ để lưu trữ các phần tử. |
Thứ tự của các phần tử (Order Of Elements) | HashSet không duy trì bất kỳ thứ tự các phần tử được thêm vào. | LinkedHashSet duy trì thứ tự chèn của các phần tử. Các phần tử được lưu trữ đúng như thứ tự chúng được chèn vào. |
Hiệu suất (Performance) | HashSet cho hiệu suất tốt hơn | Hiệu suất của nó hầu như tương tự như HashSet. Nhưng hơi chậm hơn vì nó cũng duy trì LinkedList nội bộ để duy trì trình tự chèn các phần tử. |
Thao tác thêm (Insertion), xóa (Removal) và truy xuất (Retrieval) phần tử | HashSet cho hiệu suất của lệnh O(1) để chèn, loại bỏ và truy xuất phần tử. | LinkedHashSet cũng cho hiệu suất của lệnh O(1) để chèn, loại bỏ và truy xuất phần tử. |
So sánh các phần tử | HashSet sử dụng các phương thức equals() và hashCode() để so sánh các phần tử và do đó loại bỏ các phần tử có thể trùng lặp. | LinkedHashSet cũng sử dụng phương thức equals() và hashCode() để so sánh các phần tử. |
Phần tử Null | HashSet cho phép tối đa một phần tử null. | LinkedHashSet cũng cho phép tối đa một phần tử null. |
Sử dụng bộ nhớ | HashSet đòi hỏi ít bộ nhớ hơn LinkedHashSet vì nó chỉ sử dụng HashMap nội bộ để lưu trữ các phần tử của nó. | LinkedHashSet yêu cầu bộ nhớ nhiều hơn HashSet vì nó cũng duy trì LinkedList cùng với HashMap để lưu trữ các phần tử của nó. |
Khi nào sử dụng? | Sử dụng HashSet nếu bạn muốn danh sách không chứa phần tử trùng và không cần duy trì bất kỳ thứ tự các phần tử được chèn vào. | Sử dụng LinkedHashSet nếu bạn muốn danh sách không chứa phần tử trùng và muốn duy trì thứ tự chèn của các phần tử. |
Kết
Sau những phần phân tích trên, chúng ta có thể thấy được rằng 2 cấu trúc này đều rất hữu dụng trong việc lập trình sử dụng ngôn ngữ Java. HashSet thường được sử dụng khi bạn cần một tập hợp các phần tử duy nhất và không quan trọng về thứ tự chúng. Nó có tốc độ nhanh cho việc tìm kiếm, thêm và xóa phần tử. Trong khi đó, LinkedHashSet nên được ưu tiên hơn khi bạn cần một tập hợp có duy trì thứ tự chèn các phần tử. Tùy thuộc vào yêu cầu cụ thể của ứng dụng, bạn có thể linh hoạt lựa chọn giữa 2 tập hợp để đáp ứng hiệu suất ứng dụng của mình.
Stringee Communication APIs là giải pháp cung cấp các tính năng giao tiếp như gọi thoại, gọi video, tin nhắn chat, SMS hay tổng đài CSKH cho phép tích hợp trực tiếp vào ứng dụng/website của doanh nghiệp nhanh chóng. Nhờ đó giúp tiết kiệm đến 80% thời gian và chi phí cho doanh nghiệp bởi thông thường nếu tự phát triển các tính năng này có thể mất từ 1 - 3 năm.
Bộ API giao tiếp của Stringee hiện đang được tin dùng bởi các doanh nghiệp ở mọi quy mô, lĩnh vực ngành nghề như TPBank, VOVBacsi24, VNDirect, Shinhan Finance, Ahamove, Logivan, Homedy, Adavigo, bTaskee…
Quý bạn đọc quan tâm xin mời đăng ký NHẬN TƯ VẤN TẠI ĐÂY: