So sánh HashSet, LinkedHashSet và TreeSet trong Java

Trong các bài viết trước, tôi đã giới thiệu với các bạn HashSetLinkedHashSet và TreeSet. Trong bài này, tôi sẽ so sánh sự giống nhau, khác nhau của 3 collection này.

1. Giống nhau của HashSet, LinkedHashSet và TreeSet

  • Cả ba không cho phép các phần tử trùng lặp.
  • Cả ba không được đồng bộ (non-synchronized).
  • Cả ba đều cài đặt interface Cloneable và Serializable.
  • Cả ba đề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.

Ví dụ:

package com.maixuanviet.collection.set.linkedhashset;
 
public class Student {
    private int id;
    private String name;
 
    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }
 
    @Override
    public String toString() {
        return "Student [id=" + id + ", name=" + name + "]";
    }
}
package com.maixuanviet.collection.set.linkedhashset;
 
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
 
public class LinkedHashSetExample3 {
    public static void main(String[] args) {
        // Create list
        Set<Student> students = new LinkedHashSet<>();
        // Add element to list
        Student student1 = new Student(1, "myname1");
        Student student2 = new Student(2, "myname2");
        Student student3 = new Student(3, "myname3");
        students.add(student1);
        students.add(student2);
        students.add(student3);
 
        // Show list student
        Iterator<Student> it = students.iterator();
        students.remove(student2); // You will get ConcurrentModificationException
                            // if they are modified after the creation of Iterator object.
        while (it.hasNext()) {
            Student s = (Student) it.next();
            System.out.println(s);
        }
    }
}

Thực thi chương trình trên, bạn sẽ nhận được lỗi như sau:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:719)
    at java.util.LinkedHashMap$LinkedKeyIterator.next(LinkedHashMap.java:742)
    at com.maixuanviet.collection.set.linkedhashset.LinkedHashSetExample3.main(LinkedHashSetExample3.java:24)

2. Khác nhau của HashSet, LinkedHashSet và TreeSet

HashSetLinkedHashSetTreeSet
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ử.TreeSet sử dụng TreeMap 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.TreeSet duy trì thứ tự các phần tử theo bộ so sánh được cung cấp (Comparator). Nếu không có bộ so sánh được cung cấp, các phần tử sẽ được đặt theo thứ tự tăng dần tự nhiên của chúng.
Hiệu suất (Performance)HashSet cho hiệu suất tốt hơn so với LinkedHashSet và TreeSet.Hiệu suất của LinkedHashSet nằm giữa HashSet và TreeSet. 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ử.TreeSet cho hiệu suất thấp hơn HashSet và LinkedHashSet vì nó phải sắp xếp các phần tử sau mỗi lần chèn và loại bỏ.
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ử.TreeSet cho hiệu suất của lệnh O(log (n)) cho các thao tác 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ử.TreeSet sử dụng phương pháp compare() hoặc compareTo() để so sánh các phần tử và do đó loại bỏ các phần tử có thể trùng lặp. Nó không sử dụng các phương thức equals () và hashCode () để so sánh các phần tử.
Phần tử NullHashSet 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.TreeSet không cho phép chứa phần tử null. Nếu bạn cố gắng để chèn null thành phần TreeSet, nó ném NullPointerException.
Sử dụng bộ nhớHashSet đòi hỏi ít bộ nhớ hơn LinkedHashSet và TreeSet 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ó.TreeSet cũng yêu cầu bộ nhớ nhiều hơn HashSet vì nó cũng duy trì bộ so sánh để sắp xếp các phần tử cùng với TreeMap.
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ử.Sử dụng TreeSet nếu bạn muốn danh sách không chứa phần tử trùng và muốn sắp xếp các phần tử theo một số so sánh.

Related posts:

How to Break from Java Stream forEach
Loại bỏ các phần tử trùng trong một ArrayList như thế nào?
Java Program to Solve a Matching Problem for a Given Specific Case
Java Program to Implement Binary Heap
Getting Started with GraphQL and Spring Boot
Java Program to Implement Rolling Hash
Java Program to Implement Heap Sort Using Library Functions
Merging Streams in Java
Hướng dẫn sử dụng Printing Service trong Java
Composition, Aggregation, and Association in Java
Java Program to Implement Depth-limited Search
Sử dụng JDBC API thực thi câu lệnh truy vấn dữ liệu
Spring Cloud AWS – Messaging Support
How to Find an Element in a List with Java
Java Program to Generate Randomized Sequence of Given Range of Numbers
Java Program to Implement Counting Sort
Request a Delivery / Read Receipt in Javamail
A Custom Data Binder in Spring MVC
Java Program to Check whether Graph is a Bipartite using DFS
Collect a Java Stream to an Immutable Collection
Java Program to Implement wheel Sieve to Generate Prime Numbers Between Given Range
Java Program to Implement Pollard Rho Algorithm
4 tính chất của lập trình hướng đối tượng trong Java
Java Program to Implement Hash Trie
Java Program to Implement the One Time Pad Algorithm
Hướng dẫn sử dụng Java Reflection
Java Program to do a Depth First Search/Traversal on a graph non-recursively
Spring MVC Tutorial
Check If a String Is Numeric in Java
Spring Boot - Tomcat Port Number
Converting Between an Array and a Set in Java
Java Program to Implement LinkedHashSet API