[Java Backend Zero to Hello] BÀI 1.10: COLLECTIONS FRAMEWORK (PHẦN 1)
📚 Bài viết thuộc series Java Backend Zero to Hello 📌 Phần: Phase 1: Java Core Cơ Bản | Bài 12/86
BÀI 1.10: COLLECTIONS FRAMEWORK (PHẦN 1)
Mục tiêu
- Hiểu Collections Framework và các interface chính
- Sử dụng List, ArrayList, LinkedList
- Sử dụng Set, HashSet, TreeSet, LinkedHashSet
- Thực hành các thao tác thường gặp
1. TỔNG QUAN COLLECTIONS FRAMEWORK
Collections Framework cung cấp các cấu trúc dữ liệu và thuật toán để lưu trữ, thao tác nhóm đối tượng.
Hệ thống phân cấp
Collection (interface)
├── List (interface) - Có thứ tự, cho phép trùng
│ ├── ArrayList
│ ├── LinkedList
│ └── Vector, Stack
├── Set (interface) - Không trùng
│ ├── HashSet
│ ├── LinkedHashSet
│ └── TreeSet
└── Queue (interface) - Hàng đợi
├── PriorityQueue
└── ArrayDeque
Map (interface) - Cặp key-value
├── HashMap
├── LinkedHashMap
├── TreeMap
└── Hashtable
Lợi ích
- Giảm effort lập trình
- Tăng hiệu năng với cấu trúc tối ưu
- Code dễ đọc, dễ bảo trì
- Chuẩn hóa API
2. LIST INTERFACE
Đặc điểm: Có thứ tự, cho phép phần tử trùng, truy cập theo index.
2.1 ArrayList
- Dựa trên mảng động
- Truy cập nhanh O(1)
- Thêm/xóa cuối nhanh, giữa chậm O(n)
import java.util.ArrayList;
import java.util.List;
List<String> list = new ArrayList<>();
// Thêm phần tử
list.add("Java");
list.add("Python");
list.add("JavaScript");
list.add(1, "C++"); // Thêm tại vị trí 1
// Truy cập
String first = list.get(0); // "Java"
int size = list.size(); // 4
// Cập nhật
list.set(0, "Kotlin");
// Xóa
list.remove(0); // Xóa theo index
list.remove("Python"); // Xóa theo giá trị
// Kiểm tra
boolean contains = list.contains("Java");
int index = list.indexOf("JavaScript");
// Duyệt
for (String s : list) {
System.out.println(s);
}
list.forEach(System.out::println);
2.2 LinkedList
- Dựa trên danh sách liên kết đôi
- Thêm/xóa nhanh O(1)
- Truy cập chậm O(n)
import java.util.LinkedList;
LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("A");
linkedList.add("B");
linkedList.addFirst("First"); // Thêm đầu
linkedList.addLast("Last"); // Thêm cuối
String first = linkedList.getFirst();
String last = linkedList.getLast();
linkedList.removeFirst();
linkedList.removeLast();
2.3 So sánh ArrayList vs LinkedList
| Tiêu chí | ArrayList | LinkedList |
|---|---|---|
| Cấu trúc | Mảng động | Danh sách liên kết |
| Truy cập | O(1) | O(n) |
| Thêm cuối | O(1) amortized | O(1) |
| Thêm giữa | O(n) | O(1) |
| Xóa | O(n) | O(1) |
| Bộ nhớ | Ít hơn | Nhiều hơn (lưu con trỏ) |
| Khi nào dùng | Truy cập nhiều | Thêm/xóa nhiều |
💡 Best practice: Mặc định dùng
ArrayList, chỉ dùngLinkedListkhi thêm/xóa nhiều ở đầu/giữa.
3. SET INTERFACE
Đặc điểm: Không cho phép phần tử trùng, không đảm bảo thứ tự (trừ một số loại).
3.1 HashSet
- Dựa trên HashMap
- Không đảm bảo thứ tự
- Thêm/tìm/xóa O(1)
import java.util.HashSet;
import java.util.Set;
Set<String> set = new HashSet<>();
set.add("Apple");
set.add("Banana");
set.add("Apple"); // Không thêm (đã tồn tại)
set.add("Cherry");
System.out.println(set.size()); // 3
// Kiểm tra
boolean has = set.contains("Apple");
// Xóa
set.remove("Apple");
// Duyệt
for (String s : set) {
System.out.println(s);
}
3.2 LinkedHashSet
- Duy trì thứ tự thêm vào
- Chậm hơn HashSet một chút
Set<String> linkedSet = new LinkedHashSet<>();
linkedSet.add("C");
linkedSet.add("A");
linkedSet.add("B");
// Thứ tự: C, A, B
3.3 TreeSet
- Sắp xếp tự động (theo Comparable hoặc Comparator)
- Thêm/tìm/xóa O(log n)
import java.util.TreeSet;
Set<Integer> treeSet = new TreeSet<>();
treeSet.add(5);
treeSet.add(1);
treeSet.add(3);
// Thứ tự: 1, 3, 5
// Lấy phần tử đầu/cuối
int first = treeSet.first(); // 1
int last = treeSet.last(); // 5
// Lấy phần tử nhỏ hơn/lớn hơn
Integer lower = treeSet.lower(3); // 1
Integer higher = treeSet.higher(3); // 5
3.4 So sánh các Set
| Tiêu chí | HashSet | LinkedHashSet | TreeSet |
|---|---|---|---|
| Thứ tự | Không | Thứ tự thêm | Sắp xếp |
| Hiệu năng | O(1) | O(1) | O(log n) |
| Null | Cho phép 1 null | Cho phép 1 null | Không cho phép |
4. ITERATOR
Duyệt collection theo cách thống nhất.
List<String> list = Arrays.asList("A", "B", "C");
// Iterator
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
if (s.equals("B")) {
it.remove(); // Xóa an toàn khi duyệt
}
}
// ListIterator (chỉ List) - duyệt 2 chiều
ListIterator<String> listIt = list.listIterator();
while (listIt.hasNext()) {
System.out.println(listIt.next());
}
while (listIt.hasPrevious()) {
System.out.println(listIt.previous());
}
5. CÁC THAO TÁC THƯỜNG GẶP
5.1 Chuyển đổi giữa Array và List
// Array → List
String[] arr = {"A", "B", "C"};
List<String> list = Arrays.asList(arr); // Fixed-size list
List<String> list2 = new ArrayList<>(Arrays.asList(arr)); // Mutable
// List → Array
String[] arr2 = list.toArray(new String[0]);
5.2 Collections utility methods
import java.util.Collections;
List<Integer> nums = new ArrayList<>(Arrays.asList(3, 1, 4, 1, 5, 9, 2, 6));
Collections.sort(nums); // Sắp xếp tăng dần
Collections.reverse(nums); // Đảo ngược
Collections.shuffle(nums); // Xáo trộn
Collections.fill(nums, 0); // Điền 0
int max = Collections.max(nums); // Lớn nhất
int min = Collections.min(nums); // Nhỏ nhất
int freq = Collections.frequency(nums, 1); // Đếm tần suất
5.3 So sánh
// equals - so sánh nội dung
boolean isEqual = list1.equals(list2);
// removeAll, retainAll
list1.removeAll(list2); // Xóa phần tử có trong list2
list1.retainAll(list2); // Giữ lại phần tử có trong list2
6. BÀI TẬP THỰC HÀNH
Bài 1: Quản lý danh sách sinh viên
public class StudentManager {
private List<Student> students = new ArrayList<>();
public void add(Student s) { students.add(s); }
public void remove(String id) {
students.removeIf(s -> s.getId().equals(id));
}
public List<Student> findByName(String name) {
return students.stream()
.filter(s -> s.getName().contains(name))
.collect(Collectors.toList());
}
public void sortByGpa() {
students.sort(Comparator.comparingDouble(Student::getGpa).reversed());
}
}
Bài 2: Tìm phần tử trùng lặp
public static Set<Integer> findDuplicates(List<Integer> list) {
Set<Integer> seen = new HashSet<>();
Set<Integer> duplicates = new HashSet<>();
for (Integer num : list) {
if (!seen.add(num)) {
duplicates.add(num);
}
}
return duplicates;
}
Bài 3: Loại bỏ trùng lặp giữ thứ tự
public static List<Integer> removeDuplicates(List<Integer> list) {
return new ArrayList<>(new LinkedHashSet<>(list));
}
Bài 4: Tập hợp số nguyên tố
Dùng TreeSet<Integer> để lưu các số nguyên tố từ 1 đến N.
7. TÓM TẮT
| Collection | Đặc điểm | Khi nào dùng |
|---|---|---|
| ArrayList | Mảng động, truy cập nhanh | Truy cập nhiều |
| LinkedList | Liên kết đôi, thêm/xóa nhanh | Thêm/xóa nhiều |
| HashSet | Không trùng, không thứ tự | Tập hợp không trùng |
| LinkedHashSet | Không trùng, có thứ tự thêm | Cần thứ tự thêm |
| TreeSet | Không trùng, sắp xếp | Cần sắp xếp |
Bài tiếp theo: 1.11 Collections Framework (phần 2)
🧭 Điều Hướng Series
⬅️ Bài trước: BÀI 1.9: XỬ LÝ NGOẠI LỆ (EXCEPTION HANDLING)
📋 Lộ trình tổng quan: Xem Toàn Bộ Series
➡️ Bài tiếp theo: BÀI 1.11: COLLECTIONS FRAMEWORK (PHẦN 2)
All Rights Reserved