0

[Java Backend Zero to Hello] BÀI 1.10: COLLECTIONS FRAMEWORK (PHẦN 1)

Java Backend Zero to Hello

📚 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ùng LinkedList khi 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

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí