Java collections framework: Set interface và lớp HashSet

Đây là bài 46/62 bài của series môn học Ngôn ngữ lập trình Java

1. Set interface trong Java

Set interface trong Java Collections framework giúp lưu trữ một tập hợp (set). Set interface kế thừa từ Collection interface. Set interface không bao gồm 2 phần tử giống nhau còn List interface thì có thể bao gồm các phần tử giống nhau.

Những lớp kế thừa Set interface

Các lớp kế thừa Set interface trong Java

Chúng ta cần import java.util.Set để sử dụng Set interface.

Set<String> animals = new HashSet<>();

Trong ví dụ trên, chúng ta tạo đối tượng animals của lớp HashSet.

Các phương thức của Set interface

Set interface bao gồm các phương thức của Collection interface. Ngoài ra, Set interface còn có những phương thứ khác:

  • add() thêm phần tử vào Set.
  • addAll() thêm tất cả phần tử của một Set vào một Set khác.
  • iterator() trả về một đối tượng iterator để truy cập các phần tử của Set.
  • remove() xóa một phần tử trong Set.
  • removeAll() xóa tất cả phần tử trong Set mà những phần tử này có tồn tại trong một Set khác.
  • retainAll() giữ lại tất cả những phần tử trong một tập hợp mà những phần tử này có tồn tồn tại trong một Set khác.
  • clear() xóa tất cả phần tử trong Set.
  • size() trả về số lượng phần tử trong Set.
  • toArray() trả về một mảng (array) bao gồm các phần tử của Set
  • contains() trả về true nếu Set bao gồm một phần tử nào đó.
  • containsAll() trả về true nếu Set bao gồm tất cả các phần tử trong một Set nào đó.
  • hashCode() trả về hash code value, tức là địa chỉ của phần tử trong Set.

2. Lớp HashSet trong Java

Lớp HashSet kế thừa từ Set interface và giúp lưu trữ cấu trúc dữ liệu dạng hash table.

HashSet kế thừa Set interface

Tạo ra một HashSet

Để tạo ra một HashSet, chúng ta phải import java.util.HashSet và tạo đối tượng HashSet với cú pháp sau:

HashSet<Type> numbers = new HashSet<>(8, 0.6);

Trong đó, numbers là đối tượng HashSet được tạo ra. Type là kiểu dữ liệu của các phần tử trong HashSet. Lưu ý: Không thể dùng các kiểu dữ liệu nguyên thủy cho HashSet mà phải sử dụng Wrapper Class.

Có 2 tham số khi tạo HashSet trong cú pháp new HashSet<>(10, 0.6);. Tham số đầu tiên là capacity, tham số thứ 2 là loadFactor.

  • capacity được thiết lập là 10. Có nghĩa là HashSet ban đầu chứa được 10 phần tử.
  • loadFactor được thiết lập là 0.6. Có nghĩa là khi số lượng phần tử trong HashSet lớn hơn hoặc bằng 60% capacity thì kích thước của HashSet sẽ tăng lên gấp đôi. Ví dụ: kích thước ban đầu của HashSet capacity=10 thì nếu HashSet đã chứa 0.6×10=6 phần tử thì kích thước của HashSet tự động tăng lên capacity=20. Cứ như thế nếu HashSet chứa 0.6×20=12 phần tử thì kích thước HashSet tự động tăng lên capacity=30.

Nếu không khai báo capacityloadFactor khi khởi tạo HashSet thì capacity mặc định là 16, loadFactor mặc định là 0.75.

//HashSet với default capacity = 16 và default load factor = 0.75
HashSet<Integer> numbers1 = new HashSet<>();

Thêm phần tử vào HashSet

Sử dụng hàm add() để thêm một phần tử vào HashSet. Sử dụng hàm addAll() để thêm tất cả phần tử của một HashSet vào một HashSet khác.

import java.util.HashSet;
class Main {
    public static void main(String[] args) {
        HashSet<Integer> evenNumber = new HashSet<>();
        //thêm các phần tử vào HashSet
        evenNumber.add(2);
        evenNumber.add(4);
        evenNumber.add(6);
        System.out.println("HashSet: " + evenNumber);

        HashSet<Integer> numbers = new HashSet<>();
        //thêm các phần tử của HashSet này vào HashSet khác
        numbers.addAll(evenNumber);
        numbers.add(5);
        System.out.println("New HashSet: " + numbers);
    }
}
Kết quả
HashSet: [2, 4, 6]
New HashSet: [2, 4, 5, 6]

Truy cập các phần tử trong HashSet

Để truy cập các phần tử trong HashSet, chúng ta có thể sử dụng phương thức iterator(). Để sử dụng phương thức này cần import java.util.Iterator.

import java.util.HashSet;
import java.util.Iterator;
class Main {
    public static void main(String[] args) {
        HashSet<Integer> evenNumber = new HashSet<>();
        //thêm các phần tử vào HashSet
        evenNumber.add(2);
        evenNumber.add(4);
        evenNumber.add(6);
        System.out.println("HashSet: " + evenNumber);

        //hàm iterator() trả về một đối tượng Iterator
        Iterator<Integer> iterate = evenNumber.iterator();
        System.out.print("HashSet using Iterator: ");
        //truy cập các phần tử trong HashSet
        while(iterate.hasNext()) {
            System.out.print(iterate.next());
            System.out.print(", ");
        }
    }
}
Kết quả
HashSet: [2, 4, 6]
HashSet using Iterator: 2, 4, 6,

Xóa các phần tử trong HashSet

Sử dụng hàm remove() để xóa một phần tử trong HashSet. Sử dụng hàm removeAll() để xóa tất cả phần tử trong HashSet mà những phần tử này có tồn tại trong một HashSet khác.

import java.util.HashSet;
class Main {
    public static void main(String[] args) {
        HashSet<Integer> evenNumber = new HashSet<>();
        //thêm các phần tử vào HashSet
        evenNumber.add(2);
        evenNumber.add(4);
        evenNumber.add(6);
        System.out.println("HashSet: " + evenNumber);

        //sử dụng hàm remove()
        boolean value1 = evenNumber.remove(2);
        System.out.println("Update HashSet: " + evenNumber);

        boolean value2 = evenNumber.removeAll(evenNumber);
        System.out.println("Update HashSet: " + evenNumber);
    }
}
Kết quả
HashSet: [2, 4, 6]
Update HashSet: [4, 6]
Update HashSet: []

Kết hợp 2 HashSet

Để kết hợp 2 HashSet, chúng ta sử dụng phương thức addAll().

import java.util.HashSet;
class Main {
    public static void main(String[] args) {
        HashSet<Integer> evenNumbers = new HashSet<>();
        evenNumbers.add(2);
        evenNumbers.add(4);
        System.out.println("HashSet1: " + evenNumbers);

        HashSet<Integer> numbers = new HashSet<>();
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);
        System.out.println("HashSet2: " + numbers);
        //kết hợp (union) 2 tập hợp HashSet
        numbers.addAll(evenNumbers);
        System.out.println("Union is: " + numbers);
    }
}
Kết quả
HashSet1: [2, 4]
HashSet2: [1, 2, 3]
Union is: [1, 2, 3, 4]

Lấy phần giao của 2 HashSet

Để lấy phần giao của 2 HashSet, chúng ta sử dụng hàm retainAll().

import java.util.HashSet;
class Main {
    public static void main(String[] args) {
        HashSet<Integer> evenNumbers = new HashSet<>();
        evenNumbers.add(2);
        evenNumbers.add(4);
        System.out.println("HashSet1: " + evenNumbers);

        HashSet<Integer> numbers = new HashSet<>();
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);
        System.out.println("HashSet2: " + numbers);
        //Lấy phần giao của 2 HashSet
        evenNumbers.retainAll(numbers);
        System.out.println("Intersection is: " + evenNumbers);
    }
}
Kết quả
HashSet1: [2, 4]
HashSet2: [1, 2, 3]
Intersection is: [2]

Lấy phần khác nhau giữa 2 HashSet

Để lấy phần khác nhau giữa 2 HashSet, chúng ta có thể sử dụng hàm removeAll().

import java.util.HashSet;
class Main {
    public static void main(String[] args) {
        HashSet<Integer> evenNumbers = new HashSet<>();
        evenNumbers.add(2);
        evenNumbers.add(4);
        System.out.println("HashSet1: " + evenNumbers);

        HashSet<Integer> numbers = new HashSet<>();
        numbers.add(2);
        numbers.add(3);
        System.out.println("HashSet2: " + numbers);
        //Lấy phần khác nhau giữa 2 HashSet
        evenNumbers.removeAll(numbers);
        System.out.println("Difference : " + evenNumbers);
    }
}
Kết quả
HashSet1: [2, 4]
HashSet2: [2, 3]
Difference : [4]

Kiểm tra một HashSet có nằm trong một HashSet khác hay không

Để kiểm tra một HashSet có nằm trong của một HashSet khác hay không, chúng ta sử dụng hàm containsAll().

import java.util.HashSet;
class Main {
    public static void main(String[] args) {
        HashSet<Integer> evenNumbers = new HashSet<>();
        evenNumbers.add(2);
        evenNumbers.add(4);
        System.out.println("HashSet1: " + evenNumbers);

        HashSet<Integer> numbers = new HashSet<>();
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);
        numbers.add(4);
        System.out.println("HashSet2: " + numbers);
        //Kiểm tra evenNumbers có nằm trong numbers hay không
        boolean result = numbers.containsAll(evenNumbers);
        System.out.println("Is HashSet1 is subset of HashSet2? " + result);
    }
}
Kết quả
HashSet1: [2, 4]
HashSet2: [1, 2, 3, 4]
Is HashSet1 is subset of HashSet2? true

Sử dụng HashSet khi nào?

Trong Java, HashSet thường được sử dụng nếu chúng ta phải truy cập các phần tử một cách ngẫu nhiên. Đó là vì các phần tử trong bảng băm được truy cập bằng mã băm (hash code). Mã băm (hash code) của một phần tử là một nhận dạng duy nhất giúp xác định phần tử trong bảng băm.

HashSet không được chứa các phần tử trùng lặp. Do đó, mỗi phần tử tập hợp băm có một mã băm duy nhất.

5/5 - (1 bình chọn)
Bài trước và bài sau trong môn học<< Java collections framework: Map interface và lớp HashMapJava collections framework: Iterator interface và ListIterator interface >>
Chia sẻ trên mạng xã hội:

Trả lời

Lưu ý:

1) Vui lòng bình luận bằng tiếng Việt có dấu.

2) Khuyến khích sử dụng tên thật và địa chỉ email chính xác.

3) Mọi bình luận trái quy định sẽ bị xóa bỏ.