Cấu trúc dữ liệu .NET:
Nói thêm về lý do tại sao ArrayList và List thực sự khác nhau
Mảng
Như một người dùng tuyên bố, Mảng là bộ sưu tập "trường học cũ" (vâng, mảng được coi là một bộ sưu tập mặc dù không phải là một phần của System.Collections
). Nhưng, "trường học cũ" về mảng là gì so với các bộ sưu tập khác, tức là những bộ bạn đã liệt kê trong tiêu đề của bạn (ở đây, ArrayList và List (Of T))? Hãy bắt đầu với những điều cơ bản bằng cách nhìn vào Mảng.
Để bắt đầu, Mảng trong Microsoft .NET là "các cơ chế cho phép bạn coi một số mục [liên quan đến logic] như một bộ sưu tập duy nhất" (xem bài viết được liên kết). Điều đó nghĩa là gì? Mảng lưu trữ các thành viên riêng lẻ (các phần tử) một cách tuần tự, lần lượt từng phần trong bộ nhớ với một địa chỉ bắt đầu. Bằng cách sử dụng mảng, chúng ta có thể dễ dàng truy cập các phần tử được lưu trữ tuần tự bắt đầu tại địa chỉ đó.
Ngoài điều đó và trái với lập trình 101 khái niệm phổ biến, Mảng thực sự có thể khá phức tạp:
Mảng có thể là một chiều, đa chiều hoặc bị xáo trộn (mảng răng cưa rất đáng để đọc). Bản thân mảng không động: một khi được khởi tạo, một mảng kích thước n dự trữ đủ không gian để chứa n số lượng đối tượng. Số lượng phần tử trong mảng không thể tăng hoặc thu hẹp. Dim _array As Int32() = New Int32(100)
dự trữ đủ không gian trên khối bộ nhớ cho mảng để chứa 100 đối tượng kiểu nguyên thủy Int32 (trong trường hợp này, mảng được khởi tạo để chứa 0s). Địa chỉ của khối này được trả về _array
.
Theo bài báo, Đặc tả ngôn ngữ chung (CLS) yêu cầu tất cả các mảng phải dựa trên zero. Mảng trong .NET hỗ trợ các mảng không dựa trên; tuy nhiên, điều này là ít phổ biến hơn. Là kết quả của "tính phổ biến" của các mảng dựa trên zero, Microsoft đã dành rất nhiều thời gian để tối ưu hóa hiệu suất của chúng ; do đó, các mảng một chiều, không dựa trên (sz) là "đặc biệt" - và thực sự là cách triển khai tốt nhất của một mảng (trái ngược với đa chiều, v.v.) - bởi vì các sz có các hướng dẫn ngôn ngữ trung gian cụ thể để thao tác chúng.
Mảng luôn được truyền bằng tham chiếu (dưới dạng địa chỉ bộ nhớ) - một phần quan trọng của câu đố Array cần biết. Trong khi họ thực hiện kiểm tra giới hạn (sẽ đưa ra lỗi), kiểm tra giới hạn cũng có thể bị vô hiệu hóa trên mảng.
Một lần nữa, trở ngại lớn nhất đối với mảng là chúng không thể thay đổi kích thước. Họ có công suất "cố định". Giới thiệu ArrayList và List (Of T) cho lịch sử của chúng tôi:
ArrayList - danh sách không chung chung
Các ArrayList (cùng với List(Of T)
- mặc dù có một số khác biệt quan trọng, ở đây, giải thích sau) - có lẽ là suy nghĩ tốt nhất là việc bổ sung bên cạnh bộ sưu tập (theo nghĩa rộng). ArrayList kế thừa từ giao diện IList (hậu duệ của 'ICollection'). Bản thân ArrayLists thì cồng kềnh hơn - đòi hỏi nhiều chi phí hơn hơn - so với Danh sách.
IList
không cho phép triển khai để coi ArrayLists là danh sách có kích thước cố định (như Mảng); tuy nhiên, ngoài chức năng bổ sung được thêm bởi ArrayLists, không có lợi thế thực sự nào khi sử dụng ArrayLists có kích thước cố định như ArrayLists (trên Mảng) trong trường hợp này chậm hơn rõ rệt.
Từ cách đọc của tôi, ArrayLists không thể bị lởm chởm: "Sử dụng mảng đa chiều làm các phần tử ... không được hỗ trợ". Một lần nữa, một cái đinh khác trong quan tài của ArrayLists. ArrayLists cũng không được "gõ" - có nghĩa là, bên dưới mọi thứ, ArrayList chỉ đơn giản là một mảng đối tượng động : Object[]
. Điều này đòi hỏi rất nhiều quyền anh (ngầm) và unboxing (rõ ràng) khi triển khai ArrayLists, một lần nữa thêm vào chi phí của họ.
Suy nghĩ không có căn cứ: Tôi nghĩ rằng tôi nhớ hoặc đã đọc hoặc đã nghe từ một trong những giáo sư của mình rằng ArrayLists là đứa con khái niệm khốn của nỗ lực chuyển từ Mảng sang Bộ sưu tập kiểu Danh sách, tức là trong khi đã được cải tiến rất nhiều cho Mảng, chúng không còn là lựa chọn tốt nhất vì sự phát triển hơn nữa đã được thực hiện đối với các bộ sưu tập
Danh sách (Of T): ArrayList đã trở thành (và hy vọng là gì)
Sự khác biệt về mức sử dụng bộ nhớ đủ đáng kể để Danh sách (Of Int32) tiêu thụ ít bộ nhớ hơn 56% so với ArrayList chứa cùng loại nguyên thủy (8 MB so với 19 MB trong trình diễn được liên kết của quý ông ở trên: một lần nữa, được liên kết tại đây ) - mặc dù đây là kết quả được tổng hợp bởi máy 64 bit. Sự khác biệt này thực sự thể hiện hai điều: thứ nhất (1), một "đối tượng" kiểu Int32 đóng hộp (ArrayList) lớn hơn nhiều so với kiểu nguyên thủy Int32 thuần túy (Danh sách); thứ hai (2), sự khác biệt là theo cấp số nhân do hoạt động bên trong của máy 64 bit.
Vậy, sự khác biệt và Danh sách (Of T) là gì? MSDN định nghĩa một List(Of T)
as, "... một danh sách các đối tượng được gõ mạnh có thể được truy cập bởi chỉ mục." Điều quan trọng ở đây là bit "được gõ mạnh": Danh sách (Of T) 'nhận ra các loại và lưu trữ các đối tượng là loại của chúng. Vì vậy, một Int32
được lưu trữ như một Int32
và không phải là một Object
loại. Điều này giúp loại bỏ các vấn đề gây ra bởi quyền anh và unboxing.
MSDN chỉ định sự khác biệt này chỉ phát huy khi lưu trữ các kiểu nguyên thủy và không phải các kiểu tham chiếu. Quá, sự khác biệt thực sự xảy ra trên quy mô lớn: hơn 500 yếu tố. Điều thú vị hơn là tài liệu MSDN đọc, "Lợi thế của bạn là sử dụng triển khai cụ thể theo kiểu của lớp List (Of T) thay vì sử dụng lớp ArrayList ...."
Về cơ bản, List (Of T) là ArrayList, nhưng tốt hơn. Nó là "tương đương chung" của ArrayList. Giống như ArrayList, nó không được đảm bảo để được sắp xếp cho đến khi được sắp xếp (đi hình). Danh sách (Of T) cũng có một số chức năng được thêm vào.