Mục lục
Java cho phép chúng ta tạo ra các array với kích thước cố định hoặc có thể sử dụng ArrayList với cùng chức năng tuy nhiên kích thước của ArrayList có thể tự động tăng giảm được.
Mặc dù kích thước của ArrayList có thể tăng giảm được thế nhưng bên trong ArrayList vẫn cung cấp một đối số mà chúng ta có thể đặt giá trị tạo thời điểm khởi tạo đó là capacity. Và trong bài viết này chúng ta sẽ tập trung làm rõ capacity là gì và sự khác nhau giữa capacity và size trong array.
Kích thước của Array và ArrayList
Trong phần này chúng ta sẽ tìm hiểu khái niệm về kích thước của ArrayList và Array.
Đối với array thì chúng ta phải chỉ định rõ kích thước của nó tại thời điểm khởi tạo.
Integer[] array = new Integer[100]; System.out.println("Size of an array:" + array.length);
Output
Size of an array:100
Còn đối với ArrayList thì chúng ta có thể chỉ định capacity cho nó tại thời điểm khởi tạo. Tuy nhiên chúng ta cần lưu ý rằng capacity không phải là kích thước logic của nó.
List<Integer> list = new ArrayList<>(100); System.out.println("Size of the list is :" + list.size());
Output
Size of the list is :0
Kết quả trên chúng ta có thể hiểu rằng chưa có một phần tử nào được thêm vào arraylist. Giả sử chúng ta thêm một phần tử vào arraylist.
list.add(10); System.out.println("Size of the list is :" + list.size());
Thì kết quả sẽ là
Size of the list is :1
Như vậy chúng ta có thể hiểu rằng kích thước của arraylist chính là số lượng phần tử đang tồn tại trong nó.
ArrayList Capacity vs Size Array
Array có kích thước cố định, chúng ta phải chỉ định rõ kích thước của nó tại thời điểm khởi tạo. Do vậy size và capacity của nó đều giống nhau.
Khi chúng ta khởi tạo một array, nó sẽ phân bổ bộ nhớ theo kích thước và kiểu dữ liệu của một array. Nó khởi tạo tất cả các phần tử có giá trị null cho các kiểu tham chiếu và giá trị mặc định cho các kiểu nguyên thủy.
capacity có thể hiểu đó là sức chứa của một mảng hay arraylist, biểu thị số lượng phần tử tối đa mà chúng ta thể chứa.
Bên trong nội bộ của arraylist sử dụng một array để lưu trữ các phần tử. Thông số capacity chúng ta truyền vào tại thời điểm khởi tạo sẽ được dùng làm kích thước cho array. Còn size của arraylist vẫn sẽ là 0.
public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
Trong arraylist, size của nó có thể tăng giảm được dựa vào các hoạt động thêm hoặc xóa phần tử, và được quản lý riêng biệt với capacity.
Ngoài ra khi đạt đến ngưỡng dung lượng arraylist (tương ứng với capacity), nó sẽ tăng dung lượng để có thêm chỗ cho nhiều phần tử hơn (tăng capacity). Đồng nghĩa với việc nó sẽ tạo ra một array trong nội bộ có kích thước lớn hơn và sao chép tất cả các phần tử từ array cũ sang.
Khởi tạo ArrayList với Capacity
Chúng ta có lẽ thường xuyên bỏ qua thông số capacity khi khởi tạo một arraylist. Tuy nhiên có một số trường hợp sử dụng nó sẽ giúp tối ưu hóa hiệu suất của ứng dụng như:
ArrayList có kích thước lớn
Chúng ta nên chỉ định capacity ban đầu khi khởi tạo arraylist nếu biết chắc rằng kích thước của nó sẽ lớn. Điều này làm giảm một số hoạt động nội bộ tốn kém khi chúng ta thêm phần tử vào.
Tương tự, nếu kích thước của arraylist rất lớn, thì các hoạt động nội bộ bên trong giúp chúng ta phân bộ lại bộ nhớ có thể phân bổ nhiều bộ nhớ hơn cần thiết. Điều này là do số phần tử được tăng thêm sau mỗi lần được tính theo tỷ lệ của kích thước array hiện tại.
Tạo nhiều ArrayList có kích thước nhỏ
Nếu chúng ta có nhiều arraylist nhỏ, thì size tự động của ArrayList có thể cung cấp một tỷ lệ lớn bộ nhớ bị lãng phí. Giả sử ArrayList thích kích thước 10 với số lượng phần tử nhỏ hơn, nhưng chúng tôi chỉ lưu trữ 2 hoặc 3. Điều đó có nghĩa là 70% bộ nhớ bị lãng phí, điều này có thể thành vấn đề nếu chúng tôi có một số lượng lớn các danh sách này.
Sử dụng capacity trong trường hợp này có thể tránh được lãng phí bộ nhớ.
Sử dụng ArrayList không đúng cách
Chúng ta đã biết rằng arraylist là một giải pháp tối ưu trong trường hợp chúng ta cần một array động có thể tăng giảm kích thước và không biết trước được số lượng phần tử.
Ưu thế là vậy, tuy nhiên arraylist sẽ tiêu tốn nhiều bộ nhớ hơn array. Trong một số trường hợp sử dụng, đặc biệt với các giá trị nguyên thủy, array chuẩn có thể nhanh hơn và sử dụng ít bộ nhớ hơn arraylist.
Do vậy chúng ta nên cân nhắc sử dụng array khi có thể.
Tương tự, để lưu trữ một số lượng các phần tử không cần được chỉ mục truy cập, LinkedList có thể hoạt động hiệu quả hơn. Nó không đi kèm với bất kỳ chi phí quản lý bộ nhớ nào.
Nguồn
https://www.baeldung.com/java-list-capacity-array-size