2009-10-19 21 views

Trả lời

34

Tôi thấy câu hỏi là đối diện-

Khi nào bạn nên sử dụng một mảng trên danh sách?

Chỉ có bạn mới có một lý do cụ thể để làm như vậy (ví dụ: Những hạn chế của dự án, lo ngại Memory (không thực sự là một lý do chính đáng), vv)

Danh sách là dễ dàng hơn để sử dụng (IMO), và có nhiều hơn nữa chức năng.

Lưu ý: Bạn cũng nên cân nhắc xem có giống như một Tập hợp hay một cơ sở dữ liệu khác phù hợp hơn một Danh sách cho những gì bạn đang cố gắng làm.

Mỗi cơ sở hạ tầng, và implmentation, có ưu/nhược điểm khác nhau. Chọn những cái nổi trội ở những thứ bạn cần làm.

Nếu bạn cần get() thành O (1) cho bất kỳ mục nào? Có khả năng sử dụng một ArrayList, Cần O (1) chèn()? Có thể là một Danh sách liên kết. Cần O (1) chứa()? Có thể là một Hashset.

TLDR: Mỗi cấu trúc dữ liệu đều tốt ở một số thứ và có hại ở những thứ khác. Xem xét các mục tiêu của bạn và chọn cấu trúc dữ liệu phù hợp nhất với vấn đề đã cho.

Edit:

Một điều không lưu ý là bạn khấm khá hơn khai báo biến như giao diện của nó (ví dụ: danh sách hoặc Queue) chứ không phải là lớp hướng dẫn thi hành. Bằng cách này, bạn có thể thay đổi triển khai vào một số ngày sau đó mà không thay đổi bất kỳ điều gì khác trong mã .

Như một ví dụ:

List<String> myList = new ArrayList<String>(); 

vs

List<String> myList = new LinkedList<String>(); 

Lưu ý rằng myList là một danh sách trong cả hai ví dụ. - R. Bemrose

+0

Danh sách liên kết không phải là O (1) chèn trừ khi bạn chèn các phần tử vào đầu hoặc cuối. Mục đích chính của nó là triển khai tùy chỉnh các ngăn xếp và hàng đợi. – serg

+0

Chèn danh sách được liên kết là O (1) tại một vị trí đã biết. Bạn có thể chèn O (1) vào giữa danh sách. Tìm vị trí chèn có thể là O (n) nếu danh sách của bạn không phải là hàng đợi hoặc ngăn xếp. Sự khác biệt rất quan trọng khi cố gắng so sánh cấu trúc dữ liệu. – Dolphin

+2

Một điều không được lưu ý là bạn tốt hơn nên khai báo biến đó làm giao diện của nó (tức là Danh sách hoặc Hàng đợi) thay vì lớp triển khai của nó. Bằng cách này, bạn có thể thay đổi triển khai vào một số ngày sau đó mà không thay đổi bất kỳ điều gì khác trong mã. – Powerlord

0

Nếu bạn muốn mảng mục mở rộng (nghĩa là nếu bạn không biết kích thước của danh sách sẽ là gì trước), Danh sách sẽ có lợi. Tuy nhiên, nếu bạn muốn thực hiện, bạn thường sẽ sử dụng một mảng.

+2

Để chính xác: Nếu bạn muốn tối ưu hóa vi mô, thông thường bạn sẽ sử dụng một mảng. –

6

Khá nhiều người luôn thích một danh sách. Danh sách có nhiều chức năng hơn, đặc biệt là hỗ trợ lặp. Bạn có thể chuyển đổi một danh sách thành một mảng bất kỳ lúc nào bằng phương thức toArray().

+0

"hỗ trợ đặc biệt vòng lặp": lưu ý rằng tăng cường cho vòng lặp hỗ trợ mảng cũng như Danh sách. – akf

+0

Mặc dù không hoạt động như một trình lặp thực sự, vòng lặp for-in mới trong Java 5 cung cấp cú pháp đường để lặp qua các mảng. –

+0

Ngay, như Michael đã nói, vòng lặp for là cú pháp đường. Có những lúc bạn cần đối tượng của mình để triển khai Iterator, chẳng hạn như chuyển Lists sang những thứ như một Comparator. –

1

Tùy thuộc vào loại Danh sách.

Tốt hơn nên sử dụng LinkedList nếu bạn biết bạn sẽ chèn nhiều phần tử vào các vị trí khác với kết thúc. LinkedList không thích hợp để truy cập ngẫu nhiên (nhận phần tử thứ i).

Tốt hơn nên sử dụng ArrayList nếu bạn không biết trước, có bao nhiêu yếu tố sẽ có. ArrayList phân bổ chính xác chi phí phát triển mảng sao lưu khi bạn thêm nhiều phần tử vào nó, và phù hợp để truy cập ngẫu nhiên khi các phần tử được đặt đúng vị trí. Một ArrayList có thể được sắp xếp một cách hiệu quả.

0

Trong nhiều trường hợp, các loại bộ sưu tập sử dụng là một chi tiết thực hiện mà không nên được tiếp xúc với thế giới bên ngoài. Loại returntype chung chung của bạn càng linh hoạt hơn sau khi bạn thực hiện thay đổi.

Mảng (kiểu nguyên thủy, tức là int mới [10]) không phải là chung, bạn sẽ không thể thay đổi triển khai mà không cần chuyển đổi nội bộ hoặc thay đổi mã máy khách. Bạn có thể muốn xem xét Iterable như một returntype.

2

Nếu bạn biết bạn sẽ giữ bao nhiêu thứ, bạn sẽ muốn có một mảng. Màn hình của tôi là 1024x768 và bộ đệm pixel sẽ không thay đổi kích thước bao giờ trong khi chạy.

Nếu bạn biết bạn sẽ cần truy cập vào các chỉ mục cụ thể (đi lấy mụC# 763!), Hãy sử dụng danh sách mảng hoặc mảng được sao lưu.

Nếu bạn cần thêm hoặc xóa các mục khỏi nhóm một cách thường xuyên, hãy sử dụng danh sách được liên kết.

Nói chung, xử lý phần cứng, mảng, xử lý người dùng, danh sách.

+0

Không chắc chắn về ví dụ màn hình - bạn có thể thay đổi kích thước kích thước màn hình bất kỳ lúc nào. Điều đó thậm chí còn phổ biến nếu bạn đang sử dụng ví dụ bằng RemoteDesktop/citrix hoặc di chuyển một ứng dụng sang màn hình thứ 2. – vdr

+1

Nếu bạn di chuyển một màn hình ứng dụng sang màn hình, bạn đang xử lý một cửa sổ chứ không phải màn hình, cái gì đó liên quan đến người dùng chứ không phải phần cứng. Nếu bạn đang mở một máy tính từ xa, đó là khởi tạo/thời gian chạy mới. Tôi không muốn nitpick quá nhiều, nhưng tôi muốn đứng bởi những gì tôi nói. :) –

12

Quy tắc ngón tay cái:

  • Sử dụng một List với nhiều loại tài liệu tham khảo.
  • Sử dụng mảng cho nguyên thủy.
  • Nếu bạn phải xử lý một API đang sử dụng mảng, có thể hữu ích khi sử dụng mảng. OTOH, có thể hữu ích khi thực thi việc sao lưu phòng thủ bằng hệ thống kiểu bằng cách sử dụng List s.
  • Nếu bạn đang thực hiện rất nhiều hoạt động loại List loại trên trình tự và nó không nằm trong phần hiệu năng/bộ nhớ quan trọng, hãy sử dụng List.
  • Tối ưu hóa ở mức độ thấp có thể sử dụng mảng. Mong đợi nastiness với tối ưu hóa cấp thấp.
+2

+1 để chỉ ra lợi thế về nguyên thủy. – Yishai

3

Luôn thích danh sách.

Mảng khi

  1. varargs cho một phương pháp (tôi đoán bạn đang buộc phải sử dụng Mảng ở đây).
  2. Khi bạn muốn bộ sưu tập của mình trở thành biến thể (mảng các loại tham chiếu là biến thể).
  3. Mã quan trọng hiệu suất.
9

Hầu hết mọi người đã trả lời.

Có hầu như không có lý do chính đáng để sử dụng mảng thay vì Danh sách. Ngoại lệ chính là mảng nguyên thủy (như int[]). Bạn không thể tạo danh sách nguyên thủy (phải có List<Integer>).

Sự khác biệt quan trọng nhất là khi sử dụng Danh sách bạn có thể quyết định việc triển khai nào sẽ được sử dụng. Rõ ràng nhất là chọn LinkedList hoặc ArrayList.

Tôi muốn chỉ ra trong câu trả lời này mà lựa chọn việc thực hiện cung cấp cho bạn kiểm soát hạt rất tốt trên các dữ liệu mà chỉ đơn giản là không có sẵn cho mảng:

  1. Bạn có thể ngăn khách hàng từ sửa đổi danh sách của bạn bằng cách gói danh sách của bạn trong một Collection.unmodifiableList
  2. bạn có thể đồng bộ hóa danh sách cho đa luồng sử dụng Collection.synchronizedList
  3. bạn có thể tạo một hàng đợi chiều dài cố định với việc thực hiện các LinkedBlockingQueue
  4. ... vv

Trong mọi trường hợp, ngay cả khi bạn không muốn (hiện tại) bất kỳ tính năng bổ sung nào của danh sách. Chỉ cần sử dụng một ArrayList và kích thước nó với kích thước của mảng mà bạn đã tạo ra. Nó sẽ sử dụng một mảng trong back-end và hiệu suất khác biệt với một mảng thực sẽ không đáng kể. (trừ các mảng nguyên thủy)

Các vấn đề liên quan