Bài 2: List Interface và Các Implementations
I. Giới Thiệu Về List Interface
List là một interface trong Java Collection Framework đại diện cho một tập hợp các phần tử có thứ tự. Nó cho phép các phần tử trùng lặp và cung cấp các phương thức để truy cập và sửa đổi các phần tử dựa trên chỉ số (index).
II. Các Phương Thức Chính Trong List Interface
void add(int index, E element)
Chèn phần tử
elementvào vị tríindexchỉ định.Ví dụ:
List<String> list = new ArrayList<>(); list.add("A"); list.add("B"); list.add(1, "C"); // Chèn "C" vào vị trí thứ 1 System.out.println(list); // Output: [A, C, B]
boolean add(E element)
Thêm phần tử
elementvào cuối danh sách.Ví dụ:
List<String> list = new ArrayList<>(); list.add("A"); list.add("B"); System.out.println(list); // Output: [A, B]
E get(int index)
Trả về phần tử ở vị trí
indexchỉ định.Ví dụ:
List<String> list = new ArrayList<>(); list.add("A"); list.add("B"); String element = list.get(1); // Lấy phần tử ở vị trí thứ 1 System.out.println(element); // Output: B
E remove(int index)
Xóa phần tử ở vị trí
indexvà trả về phần tử đó.Ví dụ:
List<String> list = new ArrayList<>(); list.add("A"); list.add("B"); String removedElement = list.remove(1); // Xóa phần tử ở vị trí thứ 1 System.out.println(removedElement); // Output: B System.out.println(list); // Output: [A]
E set(int index, E element)
Thay thế phần tử ở vị trí
indexbằng phần tửelement.Ví dụ:
List<String> list = new ArrayList<>(); list.add("A"); list.add("B"); list.set(1, "C"); // Thay thế phần tử ở vị trí thứ 1 bằng "C" System.out.println(list); // Output: [A, C]
int size()
Trả về số lượng phần tử trong danh sách.
Ví dụ:
List<String> list = new ArrayList<>(); list.add("A"); list.add("B"); int size = list.size(); // Lấy số lượng phần tử trong danh sách System.out.println(size); // Output: 2
III. Các Lớp Triển Khai List Interface
ArrayList
Đặc điểm:
Dựa trên mảng động (dynamic array).
Hỗ trợ truy cập ngẫu nhiên nhanh (O(1)).
Chèn và xóa phần tử chậm ở giữa danh sách (O(n)).
Khi nào sử dụng: Khi cần truy cập các phần tử theo chỉ số thường xuyên.
Ví dụ:
List<String> arrayList = new ArrayList<>(); arrayList.add("A"); arrayList.add("B"); arrayList.add(1, "C"); System.out.println(arrayList); // Output: [A, C, B]
LinkedList
Đặc điểm:
Dựa trên cấu trúc danh sách liên kết kép (doubly-linked list).
Chèn và xóa phần tử nhanh ở giữa danh sách (O(1)).
Truy cập ngẫu nhiên chậm (O(n)).
Khi nào sử dụng: Khi cần thực hiện nhiều thao tác chèn và xóa ở giữa danh sách.
Ví dụ:
List<String> linkedList = new LinkedList<>(); linkedList.add("A"); linkedList.add("B"); linkedList.add(1, "C"); System.out.println(linkedList); // Output: [A, C, B]
Vector
Đặc điểm:
Giống như ArrayList nhưng có tính đồng bộ (synchronized).
Hiệu năng kém hơn ArrayList do tính đồng bộ.
Khi nào sử dụng: Khi cần một danh sách hỗ trợ đa luồng (multi-threading).
Ví dụ:
List<String> vector = new Vector<>(); vector.add("A"); vector.add("B"); vector.add(1, "C"); System.out.println(vector); // Output: [A, C, B]
CopyOnWriteArrayList
Đặc điểm:
Một phiên bản của ArrayList với tính đồng bộ.
Thay thế toàn bộ danh sách khi có thay đổi.
Hiệu năng tốt khi đọc nhiều hơn ghi.
Khi nào sử dụng: Khi cần một danh sách đồng bộ mà chủ yếu là thao tác đọc.
Ví dụ:
List<String> cowArrayList = new CopyOnWriteArrayList<>(); cowArrayList.add("A"); cowArrayList.add("B"); cowArrayList.add(1, "C"); System.out.println(cowArrayList); // Output: [A, C, B]
IV. So Sánh Hiệu Năng Và Trường Hợp Sử Dụng
| Lớp | Truy Cập Ngẫu Nhiên | Chèn/Xóa Ở Giữa Danh Sách | Đồng Bộ | Khi Nào Sử Dụng |
| ArrayList | Rất nhanh (O(1)) | Chậm (O(n)) | Không | Khi cần truy cập theo chỉ số thường xuyên |
| LinkedList | Chậm (O(n)) | Nhanh (O(1)) | Không | Khi cần chèn/xóa ở giữa danh sách thường xuyên |
| Vector | Nhanh (O(1)) | Chậm (O(n)) | Có | Khi cần hỗ trợ đa luồng |
| CopyOnWriteArrayList | Nhanh (O(1)) | Chậm (O(n)) | Có | Khi chủ yếu thao tác đọc trong môi trường đa luồng |
V. Kết Luận
Trong bài viết này, chúng ta đã khám phá List interface và các lớp triển khai của nó. Hiểu rõ sự khác nhau và đặc điểm của từng loại List sẽ giúp bạn chọn lựa cấu trúc dữ liệu phù hợp cho các tình huống cụ thể trong ứng dụng của mình.
VI. Tài Liệu Tham Khảo
Java SE Documentation: Java Collections Framework
"Effective Java" by Joshua Bloch: Các nguyên tắc và best practices khi sử dụng Collection Framework.
Bài Tập Thực Hành
Tạo một chương trình Java sử dụng ArrayList để lưu trữ danh sách các sinh viên và in ra danh sách này theo thứ tự.
Tạo một chương trình Java sử dụng LinkedList để lưu trữ các công việc trong một to-do list và chèn một công việc vào giữa danh sách.
Tạo một chương trình Java sử dụng Vector để lưu trữ các giao dịch ngân hàng và đảm bảo tính đồng bộ khi nhiều luồng truy cập.
Tạo một chương trình Java sử dụng CopyOnWriteArrayList để lưu trữ danh sách các yêu cầu HTTP trong một server, trong đó việc đọc là thao tác chủ yếu.
Bài viết này không chỉ giúp bạn hiểu rõ về List interface mà còn cung cấp các ví dụ cụ thể và bài tập thực hành để củng cố kiến thức. Hãy tiếp tục theo dõi các bài viết tiếp theo để khám phá thêm về Collection Framework trong Java.