Kích thước ban đầu cho ArrayList


257

Bạn có thể đặt kích thước ban đầu cho một ArrayList bằng cách thực hiện

ArrayList<Integer> arr=new ArrayList<Integer>(10);

Tuy nhiên, bạn không thể làm

arr.add(5, 10);

bởi vì nó gây ra một ngoại lệ trong giới hạn

Việc sử dụng cài đặt kích thước ban đầu là gì nếu bạn không thể truy cập vào không gian bạn đã phân bổ?

Hàm add được định nghĩa là add(int index, Object element)vì vậy tôi không thêm vào chỉ mục 10.


52
Trên thực tế, không rõ ràng từ các tài liệu mà một danh sách cần phải có ít nhất n mục được thêm vào trước khi bạn có thể set/addmục n-1 .
Nhận thức

5
Nhận thức: Tôi không biết nếu nó là hiển nhiên, nhưng nó được chỉ định. Người ta phải đọc JavaDoc một cách cẩn thận. Các lệnh: IndexOutOfBoundException - nếu chỉ mục nằm ngoài phạm vi (chỉ mục <0 | | index> = size ()).
Natix

3
Hừm, nhà xây dựng nói "Xây dựng một danh sách trống với công suất ban đầu được chỉ định.", Lấy khái niệm về một danh sách trống, không thể có một chỉ số 5. ​​Nhưng tôi đồng ý rằng điều này có thể không nhìn thấy được ngay từ cái nhìn đầu tiên ...
quaylar

12
Tôi nghĩ cũng công bằng khi nói rằng nếu bạn khởi tạo một mảng thành một giá trị cụ thể, bạn sẽ giả sử các chỉ số thấp hơn giá trị đó có sẵn và đây là một ArrayList. Cá nhân tôi muốn một phương pháp cho phép tôi đặt kích thước sao cho tôi có thể đặt mọi thứ vào các chỉ số cụ thể. Phương pháp này có vẻ vắng mặt đáng chú ý.
Andrew Wyld

1
Numbskull đã thiết kế các bộ sưu tập theo cách này?! Điều này buộc công việc dư thừa để khởi tạo song song một cấu trúc với các phần tử có độ dài thay đổi (ví dụ ArrayList <String []> trong đó mỗi mảng có thể có độ dài khác nhau). Nếu bộ nhớ đã được phân bổ để danh sách không cần phân bổ lại sau khi thêm N phần tử, các chỉ số đó sẽ có thể truy cập trực tiếp từ đầu. Không có ai ở Oracle học được mô hình này sau C / C ++, C #, Objective C và Swift?!
patrickjp93

Câu trả lời:


387

Bạn đang nhầm lẫn kích thước của danh sách mảng với khả năng của nó:

  • các kích thước là số phần tử trong danh sách;
  • các công suất là bao nhiêu yếu tố danh sách có khả năng có sức chứa mà không cần phân bổ lại các cấu trúc nội bộ của mình.

Khi bạn gọi new ArrayList<Integer>(10), bạn đang thiết lập danh sách ban đầu dung lượng , không phải kích thước của nó. Nói cách khác, khi được xây dựng theo cách này, danh sách mảng bắt đầu cuộc sống của nó trống rỗng.

Một cách để thêm mười phần tử vào danh sách mảng là sử dụng vòng lặp:

for (int i = 0; i < 10; i++) {
  arr.add(0);
}

Đã làm điều này, bây giờ bạn có thể sửa đổi các phần tử tại các chỉ số 0..9.


51
+1: Một vòng lặp ngắn hơn while(arr.size() < 10) arr.add(0);Có thể hữu ích để nói, kích thước cần phải ít nhất 10. ví dụ: vì vậy bạn có thể sử dụngarr.set(9, n);
Peter Lawrey

10
+1: Phản hồi tuyệt vời, tôi sẽ cho +10 nếu có thể. Không rõ ràng ngay lập tức từ api tại sao bạn không thể đặt CẢ HAI kích thước ban đầu và dung lượng ban đầu trong một lệnh gọi hàm tạo. Bạn phải đọc qua api và nói "Ồ, tôi đoán ArrayList không có phương thức hoặc hàm tạo để làm điều đó"
demongolem

@PeterLawrey Mã của bạn có thể ngắn hơn, nhưng chứa hai lệnh gọi phương thức trên mỗi vòng lặp, thay vì chỉ một.
thần kinh

@neuralmer Tôi mong muốn size () và add () được nội tuyến để không có cuộc gọi phương thức thực tế nào xảy ra khi chạy.
Peter Lawrey

109

Nếu bạn muốn một danh sách với kích thước được xác định trước, bạn cũng có thể sử dụng:

List<Integer> arr = Arrays.asList(new Integer[10]);

11
Bất lợi nhỏ ở đây, kết quả Listlà đầy null. Với Guava, chúng ta có thể thực hiện việc Ints.asList(new int[10])khởi tạo danh sách 0của mình bằng s. Mẫu sạch mặc dù, cảm ơn cho ví dụ.
dimo414

1
Các câu hỏi nói về ArrayList <E>. Bạn đang sử dụng Danh sách <E>. Không ai quan sát điều này ??? Hơn nữa, họ đã nêu lên câu trả lời không liên quan này ! Tôi không đánh giá thấp câu trả lời của bạn bởi vì tôi không bao giờ làm. Đơn giản là ... Godssake!
Tông đồ

3
@Apostolos ArrayListlà một triển khai của Listgiao diện và Arrays.asListtrả về một ArrayList. Tôi đề nghị bạn tìm kiếm đa hình.
Liam Potter

Điều này trả về một Danh sách với một kích thước cố định mặc dù. Cố gắng thêm nhiều yếu tố némUnsupportedOperationException
Koray Tugay

47

nếu bạn muốn sử dụng Collections.fill (list, obj); để điền vào danh sách với một đối tượng lặp đi lặp lại, bạn có thể sử dụng

ArrayList<Integer> arr=new ArrayList<Integer>(Collections.nCopies(10, 0));

dòng sao chép 10 lần 0 vào ArrayList của bạn


20

Công suất của một ArrayListkhông giống như kích thước của nó . Kích thước bằng với số lượng phần tử có trong ArrayList(và bất kỳ Listtriển khai nào khác ).

Các khả năng chỉ là chiều dài của mảng cơ bản được sử dụng để lưu trữ internaly các yếu tố của ArrayList, và luôn luôn lớn hơn hoặc bằng với kích thước của danh sách.

Khi gọi set(index, element)vào danh sách, indexliên quan đến số thực tế của các thành phần danh sách (= size) (bằng 0 trong mã của bạn, do đó AIOOBEđược ném), không liên quan đến độ dài mảng (= dung lượng) (là chi tiết triển khai cụ thể đểArrayList ).

Các setphương pháp chung cho tất cả Listhiện thực, chẳng hạn như LinkedList, mà không thực sự được thực hiện bởi một mảng, nhưng như một chuỗi liên kết các mục.

Chỉnh sửa : Bạn thực sự sử dụng add(index, element)phương pháp, không set(index, element), nhưng nguyên tắc là giống nhau ở đây.


10

Nếu bạn muốn thêm các phần tử với chỉ mục, thay vào đó bạn có thể sử dụng một mảng.

    String [] test = new String[length];
    test[0] = "add";

5
OP muốn sử dụng Danh sách ban đầu ... không phải là một mảng.
Stephan

9

10 là công suất ban đầu của AL, không phải kích thước (bằng 0). Bạn nên đề cập đến công suất ban đầu với một số giá trị cao khi bạn sẽ có nhiều yếu tố, bởi vì nó tránh được chi phí mở rộng công suất khi bạn tiếp tục thêm các yếu tố.


6

Tôi đoán một câu trả lời chính xác cho câu hỏi của bạn sẽ là:

Đặt kích thước intial trên ArrayList sẽ giảm nr. lần phân bổ lại bộ nhớ trong phải xảy ra. Danh sách được hỗ trợ bởi một mảng. Nếu bạn chỉ định tức là dung lượng ban đầu 0, thì ở lần chèn đầu tiên của một phần tử, mảng bên trong sẽ phải được thay đổi kích thước. Nếu bạn có một ý tưởng gần đúng về việc có bao nhiêu yếu tố trong danh sách của bạn, việc đặt công suất ban đầu sẽ giảm nr. phân bổ lại bộ nhớ xảy ra trong khi bạn sử dụng danh sách.


3

Điều này có thể giúp ai đó -

ArrayList<Integer> integerArrayList = new ArrayList<>(Arrays.asList(new Integer[10]));

3

Đến muộn với điều này, nhưng sau Java 8 , cá nhân tôi thấy cách tiếp cận sau đây với StreamAPI ngắn gọn hơn và có thể là một cách thay thế cho câu trả lời được chấp nhận .

Ví dụ,

Arrays.stream(new int[size]).boxed().collect(Collectors.toList())

nơi sizeđược mong muốn Listkích thước và không có nhược điểm đề cập ở đây , tất cả các yếu tố trong Listđược khởi tạo như 0.

(Tôi đã thực hiện một tìm kiếm nhanh và không thấy streamtrong bất kỳ câu trả lời nào được đăng - vui lòng cho tôi biết nếu câu trả lời này là dư thừa và tôi có thể xóa nó không)


1

Ngay bây giờ không có yếu tố nào trong danh sách của bạn để bạn không thể thêm vào chỉ mục 5 của danh sách khi nó không tồn tại. Bạn đang nhầm lẫn dung lượng của danh sách với kích thước hiện tại của nó.

Chỉ cần gọi:

arr.add(10)

để thêm Integer vào ArrayList của bạn


1

Mặc dù danh sách mảng của bạn có dung lượng 10, nhưng danh sách thực không có yếu tố nào ở đây. Phương thức add được sử dụng để chèn một phần tử vào danh sách thực. Vì nó không có phần tử, bạn không thể chèn một phần tử vào chỉ mục 5.


1

Nếu bạn muốn thêm 10 mục vào, ArrayListbạn có thể thử:

for (int i = 0; i < 10; i++)
    arr.add(i);

Nếu bạn đã khai báo một biến kích thước mảng, bạn sẽ sử dụng biến sizeđó thay vì số '10'


1

Tôi đã đối mặt với vấn đề tương tự và chỉ cần biết ArrayList là một triển khai mảng có thể thay đổi kích thước của giao diện Danh sách, tôi cũng hy vọng bạn có thể thêm phần tử vào bất kỳ điểm nào, nhưng ít nhất có tùy chọn để xác định kích thước ban đầu. Dù sao, bạn có thể tạo một mảng đầu tiên và chuyển đổi nó thành một danh sách như:

  int index = 5;
  int size = 10;

  Integer[] array = new Integer[size];
  array[index] = value;
  ...
  List<Integer> list = Arrays.asList(array);

hoặc là

  List<Integer> list = Arrays.asList(new Integer[size]);
  list.set(index, value);

0

ArrayList myList = new ArrayList (10);

//  myList.add(3, "DDD");
//  myList.add(9, "III");
    myList.add(0, "AAA");
    myList.add(1, "BBB");

    for(String item:myList){
        System.out.println("inside list : "+item);
    }

/ * Khai báo khả năng ban đầu của danh sách mảng không gì khác ngoài việc tiết kiệm thời gian thay đổi trong nội bộ; Khi chúng ta thêm phần tử vào bên trong, nó sẽ kiểm tra capasity để tăng capasity, bạn có thể thêm phần tử ở 0 chỉ số ban đầu sau đó 1 và cứ thế. * /


0

Hai xu của tôi vào Stream. Tôi nghĩ rằng tốt hơn để sử dụng

IntStream.generate(i -> MyClass.contruct())
         .limit(INT_SIZE)
         .collect(Collectors.toList());

với sự linh hoạt để đặt bất kỳ giá trị ban đầu.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.