Quay lại danh sách
Java
2024-04-10
25 phút đọc

Hiểu sâu Java Collections: List, Set, Map và cách chọn cấu trúc phù hợp

Java Collections: Chọn đúng cấu trúc dữ liệu cho bài toán của bạn

Rất nhiều dự án Java chậm không phải vì thuật toán quá phức tạp, mà vì chọn sai Collection. Ví dụ: dùng List để kiểm tra tồn tại phần tử thay vì Set, hoặc dùng HashMap nơi cần giữ thứ tự phần tử.

1. List – Khi bạn cần danh sách có thứ tự

  • ArrayList: lưu trữ liên tiếp trong bộ nhớ, truy cập theo index O(1), thêm/xoá giữa danh sách O(n).
  • LinkedList: mỗi phần tử là một node liên kết, thêm/xoá ở đầu/cuối O(1), nhưng truy cập index O(n).

Trong hầu hết trường hợp, ArrayList là lựa chọn mặc định:

List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
System.out.println(names.get(0)); // Alice

Bạn chỉ nên dùng LinkedList khi thực sự cần rất nhiều thao tác chèn/xóa ở giữa danh sách và ít truy cập ngẫu nhiên.

2. Set – Khi bạn cần giá trị duy nhất và kiểm tra tồn tại nhanh

  • HashSet: không đảm bảo thứ tự, kiểm tra tồn tại O(1) trung bình.
  • LinkedHashSet: giữ thứ tự chèn phần tử.
  • TreeSet: giữ phần tử luôn được sắp xếp (dựa trên Comparable hoặc Comparator).

Ví dụ kiểm tra trùng email nhanh chóng:

Set<String> emails = new HashSet<>();
if (!emails.add("user@example.com")) {
    System.out.println("Email đã tồn tại");
}

3. Map – Khi bạn cần ánh xạ key → value

  • HashMap: nhanh, không có thứ tự.
  • LinkedHashMap: lưu thứ tự chèn, tiện cho cache đơn giản.
  • TreeMap: duy trì key được sắp xếp.

Ví dụ dùng LinkedHashMap cho LRU cache mini:

Map<String, String> cache = new LinkedHashMap<>(16, 0.75f, true) {
    @Override
    protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
        return size() > 100;
    }
};

4. Một số best practice quan trọng

  • Luôn dùng interface (List, Set, Map) ở khai báo biến, chỉ dùng class cụ thể ở bên phải dấu new.
  • Tránh VectorHashtable trong code mới – đây là legacy, đã có lựa chọn tốt hơn.
  • Cẩn thận với ConcurrentHashMap: rất hữu ích trong môi trường multi-thread, nhưng đừng lạm dụng nơi không cần thiết.

Hiểu rõ Collections giúp bạn viết code vừa dễ đọc, vừa có hiệu năng tốt mà không cần tối ưu sớm bằng những kỹ thuật phức tạp.